数组快排的四种方法

 1.快排递归版

如上图所示

数组第一个数值为key,设立两个指针L和R从数组两边向中间移动,右边指针先移动,如果右边指针指向比key小的数值那么key继续向中间移动,直到指向的数值比key要大停止。左边指针在右边指针停止后移动,如果指向了比key数值小的那么继续向中间移动,直到指向比key要大或者与R指针指向的位置相同停下。

再左边指针停下后如果L指针和R指针没有重合那么交换L和R指向位置的数据,如果L指针和R指针重合那么交换key和R或L指针指向的数据。这样在key左边的数据就比key小在key右边的数据就比key要大。我们再来看图理解 

通过不断的递归最终达到排序的目的,使每个数都放在自己大小对应的位置。

重点:在递归只剩一个数或没有数的时候return

代码实现如下

void swap(int* a, int* b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}
void QuickSort(int* a, int left, int right)
{
	if (left >= right)
	{
		return;
	}
	if (right - left < 10)
	{
		InsertSort(a, right-left);
		return;
	}
	int mid = Getmid(a, left, right);
	swap(&a[left], &a[mid]);
	int key1 = left;
	int begin = left + 1, end = right;
	while (begin < end)
	{
		while (a[end] > a[key1] && begin != end)
		{
			end--;
		}
		while (a[begin] < a[key1]&& begin!=end)
		{
			begin++;
		}
		swap(&a[begin], &a[end]);
		if (begin == end)
		{
			swap(&a[key1], &a[end]);
		}
	}

	QuickSort(a, end + 1, right);
	QuickSort(a, left, end - 1);

}

2.快排非递归

快排非递归和递归相似,主要是要考虑如何存放数据(函数处理时左右的位置数据)

我们可以设置一个栈来存储数据left 和 right

每次排完序将两边的左右位置数据放入栈中,下一次排序在将栈中的数据拿出来用,用完再将两边的数据放入栈中,当两边其中有一边的数据个数只有一个或者是一个数据都没有,那么就不需要将左右两边的位置数据放入栈中。当栈中没有数据时停止循环,排序结束。

代码实现如下

void swap(int* a, int* b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}
int PartSort1(int* a, int left, int right)
{
	int MID = Getmid(a, left, right);
	swap(&a[left], &a[MID]);
	int begin = left;
	int keyi = left;
	int end = right;
	while (begin<end)
	{
		while (a[keyi] <= a[end] &&  begin < end)
		{
			end--;
		}
		while (a[keyi] >= a[begin] && begin < end)
		{
			begin++;
		}
		swap(&a[begin], &a[end]);
	}
	swap(&a[keyi], &a[begin]);
	return begin;
}
void QuickSortNonR(int* a, int left, int right)
{
	ST SQ;
	STInit(&SQ);
	int begin = left;
	int end = right;
	STPush(&SQ, begin);
	STPush(&SQ, end);
	while (!STEmpty(&SQ))
	{
		end = STTop(&SQ);
		STPop(&SQ);
		begin = STTop(&SQ);
		STPop(&SQ);
		int keyi = PartSort1(a, begin, end);
		if (keyi - 1> begin)
		{
			STPush(&SQ, begin);
			STPush(&SQ, keyi - 1);
		}
		if (keyi + 1 < end)
		{
			STPush(&SQ, keyi + 1);
			STPush(&SQ, end);
		}
	}
}

3.快排前后指针法

快排前后指针依然是设立数组第一个数为key,然后设立两个指针front和back,front指向key的下一个位置,back指向key,排序时back向前走一步,然后front再向前走一步,如果front指向的值比key要大那么front继续向前走一步,如果front指向的值要比key要小那么back向前走一步,并且back指向的值与front进行交换,直到front指向的位置超出数组停止循环,key指向的数值与back进行交换,完成一次排序。

具体流程请看VCR

代码实现如下 

void swap(int* a, int* b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}
int PartSort3(int* a, int left, int right)
{
	int head = left+1, tail = left;
	while (head <= right&& head>tail)
	{
		if (a[head] >= a[left])
		{
			head++;
		}
		else
		{
			tail++;
			swap(&a[tail], &a[head]);
		}
	}
	swap(&a[tail], &a[left]);
	return tail;
}

4.快排挖坑法 

设立一个整形变量key存储数组第一个数,将数组第一个数置为0(不置也没关系)

再设立两个指针一个L指向数组第二个节点,一个R指向数组最后一个节点,从R开始,向中间遍历直到遇到比key小的数停下,然后L指针开始从数组左边向中间遍历直到遇到比key大的数据停下,当L停下后将R指向的数据放入空的位置中将L的数据放入R中,然后继续这样的循环直到L遇上了R,那么他们指向的数据放入空的位置中再将key的数据放入L中便完成了一次排序

代码实现如下

void swap(int* a, int* b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}
int PartSort2(int* a, int left, int right)
{
	int MID = Getmid(a, left, right);
	swap(&a[left], &a[MID]);
	int begin = left;
	int keyi = left;
	int num = a[left];
	int end = right;
	while (begin < end)
	{
		while (num <= a[end] && begin < end)
		{
			end--;
		}
		swap(&a[keyi], &a[end]);
		keyi = end;
		while (num >= a[begin] && begin < end)
		{
			begin++;
		}
		swap(&a[begin], &a[keyi]);
		keyi = begin;
	}
	a[keyi] = num;
	return begin;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值