单链表的快排实现

题目:对单链表,实现快速排序

思路:(2017.9.17增加)其实对比快排的经典实现,改进的地方主要有两个:1、是从一个方向处理切分的,维系两个指针,一个指针quick用于遍历,一个指针slow用于记录,已经处理过的,所有小于枢轴的最后一个值。那么小于等于slow位置的元素都小于枢轴;在slow和quick之间的元素都大于枢轴,quick后面的元素还未处理。一旦quick指向的元素小于枢轴,那么slow++(其指向的值肯定不小于枢轴),与quick交换。2、区间的最后一个元素不处理。

思路(升序):快速排序的主要操作是用选取的枢轴作为切割的基准,左侧所有元素均小于枢轴,右侧均不小于枢轴。经典实现是从头和尾两个方向进行处理,由于单链表的移动方向是单向的,所以必须寻求其他方式。

用一个指针遍历链表,遇到小于枢轴的元素,就将其移到链表的开始处,剩下的就是不小于枢轴的元素;为了实现上述目标,建立两个指针,一个指针指向所有元素都小于枢轴的子链表,一个指针用于遍历。

注意:

1、枢轴一定要放到中间位置,不能放到起始点,也就是循环退出后,要进行一次交换。

2、切分的最后一个元素是不参与处理的。可以看到,经典实现若枢轴位置为  par,那么用的是par-1,par+1。由于单链表不能往前回溯,这个版本实现最后元素不处理,所以用的是par,par+1,可以实现相同的效果。

#include  
#include
using namespace std;
typedef struct node
{
	node *next;
	int data;
	node() :next(NULL), data(0){}
}node,*list;

void swap(int &a,int &b)
{
	int temp;
	temp = a;
	a = b;
	b = temp;
}

node *change(vector &a)
{
	node *list = new node();
	node *temp;
	node *tail = list;
	for (int i = 0; i < a.size(); i++)
	{
		temp = new node();
		temp->data = a[i];
		tail->next = temp;
		tail = temp;
	}
	return list;
}

node *partation(node *low, node *hi)
{
	int key = low->data;
	node *pslow = low;
	node *pquick = low->next;
	
	while (pquick != hi)
	{
		if (pquick->data < key)
		{
			pslow = pslow->next;
			swap(pslow->data, pquick->data);
		}
		pquick = pquick->next;
	}
	swap(pslow->data, low->data);
	return pslow;
}

void quicksort(node *low,node *hi)
{
	if (low == hi) return;
	node *par = partation(low, hi);
	quicksort(low, par);    //因为最后一个元素不处理
	quicksort(par->next, hi);
}

void sort(list lis)
{
	quicksort(lis->next,NULL);
}

void listprint(list lis)
{
	node *p = lis->next;
	while(p)
	{
		cout << p->data << " ";
		p = p->next;
	}
	cout << endl;
}

int main()
{
	vector data = {9,3,7,5,8};
	list lis = change(data);
	sort(lis);
	listprint(lis);
	system("pause");
	return   0;
}


你可能感兴趣的:(算法)