快速排序

首先快速排序有三种方式下面我来一一介绍

1.最基本的方式,基准值法

算法描述:取第一个或最后一个元素为基准值(我在这里取第一个元素),然后定义两个标记left和right分别指向数组的起始位置和最后一个位置,然后right从后往前走找到小于基准值的时候停下来,left开始往后走,找到大于基准值的元素的停下来,然后交换arr[left]和array[right]的值,重复上述步骤直到left>=right然后将基准值和当前停下来的位置交换,这个时候数组就以基准值为基础被分为两部分,如果基准值左边的元素全部小于基准值,基准右边的元素全部大于基准值。然后递归处理每个组就可以了。


下面给出算法代码:

int postion(int *array, int left, int right)
{
	int key = left;//要更换当前位置上面的值,所以只能取下标,如果取array[left]的话则left位置的元素无法更换
	while (left < right)
	{
		while (left<right&&array[key]<=array[right])//这里要取到等号
		{
			--right;
		}
		while (left<right&&array[key]>=array[left])
		{
			++left;
		}
		if (left<right)//会有相遇的时候这个时候不交换避免重复交换
			swap(array[left], array[right]);
	}
	swap(array[key], array[left]);
	return left;
}
void QuickSort(int *arr, int left, int right)//这里的right不会变得
{
	if (left < right)
	{
		int n = postion(arr, left, right);
		QuickSort(arr, left, n - 1);//key之前的分组
		QuickSort(arr, n + 1, right);//key之后的分组
	}
}
注意取等号和让key取下标!这是必须的!

方法2:挖坑法

算法描述:这个也是在基准值得基础上演变的,首先取首元素为基准值(尾元素也可以),让key=array[0],这个时候相当于第一个元素被挖走了,这里就成了一个坑,然后此时right从后往前找比key小的元素就填到array[0]的位置这个时候array[0]的这个坑被填了,那么array[right]这里又是一个坑了,所以再让left从前往后找比key大的元素(注意这里只能是大或者小不能取等于),然后将array[right]的坑填了,然后让right继续从后面找填上一个坑,依此类推,直到left==right此时此处必定为一个坑,然后将key值填进去就好了,这个时候数组也被分成了两组和上述情况一样,然后递归调用就可以了。

下面给出算法代码

int postion(int *array, int left, int right)
{
	int key = array[left];//因为最后是用值来替换所以就记录他的下标就可以了
	while (left<right)
	{
		while(left<right&&array[right] >= key)
		{
			--right;
		}
		if (left < right)
			array[left] = array[right];
		while (left<right&&array[left] <= key)
		{
			left++;
		}
		if (left < right)
			array[right] = array[left];
	}
	array[left] = key;
	return left;
}
void QuickSort(int *array, int left, int right)
{
	if (left < right)
	{
		int  n = postion(array, left, right);
		QuickSort(array, left, n - 1);
		QuickSort(array, n + 1, right);
	}
}
方法3:双指针法

算法描述:同样取最后一个元素为基准值,然后定义两个指针(指向下标的所以这里说得是指针),fast指向left,slow指向left-1,然后fast开始走,找到比array[right]小的元素则slow开始走,当slow走完以后判断fast是否等于slow,如果不等于交换arr[slow]和arr[fast],相等的话不交换,然后fast继续走,如果所指的数都大于arr[right]则slow不动,当fast==right的时候循环结束,此时slow++然后交换arr[slow]和arr[right],此时数组也被分成了两组,同上进行递归调用

算法代码如下:

int postion(int *array, int left, int right)
{
	Keydata(array, left, right);
	int fast = left;//先走
	int slow = left - 1;//后走
	while (fast<right)
	{
		if (array[fast] < array[right])
		{
			++slow;
			if (slow != fast)
				swap(array[slow], array[fast]);
		}
		fast++;
	}
	++slow;
	swap(array[slow], array[right]);
		return slow;
}
void QuickSort(int *arr, int left, int right)
{

	if (left < right)
	{
		int n = postion(arr, left, right);
		QuickSort(arr, left, n - 1);
		QuickSort(arr, n+1, right);
	}
}
对于快排的优化,这里我只说一个其余的感兴趣自己查阅相关资料,就是三数取中间值得方法,即其数组首尾和中间元素的值,找出三个中中间大小的值作为基准值,这样效率会比较高,下面给出找中间值得代码

void KeyMiddata(int *array, int left,int right)//优化取三个元素的中间值的元素
{
	int mid = (right - left) / 2 + left;
	if (array[mid] > array[left] && array[mid] < array[right])
	{
		swap(array[mid], array[right]);
		return;
	}

	if (array[left]>array[mid] && array[left] < array[right])
	{
		swap(array[left], array[right]);
		return;
	}
	if (array[right]>array[mid] && array[right] < array[left])
		 return;
}
优化后的快排

void KeyMiddata(int *array, int left,int right)//优化取三个元素的中间值的元素
{
	int mid = (right - left) / 2 + left;
	if (array[mid] > array[left] && array[mid] < array[right])
	{
		swap(array[mid], array[right]);
		return;
	}

	if (array[left]>array[mid] && array[left] < array[right])
	{
		swap(array[left], array[right]);
		return;
	}
	if (array[right]>array[mid] && array[right] < array[left])
		 return;
}
int postion(int *array, int left, int right)
{
	KeyMiddata(array, left, right);
	int fast = left;//先走
	int slow = left - 1;//后走
	while (fast<right)
	{
		if (array[fast] < array[right])
		{
			++slow;
			if (slow != fast)
				swap(array[slow], array[fast]);
		}
		fast++;
	}
	++slow;
	swap(array[slow], array[right]);
		return slow;
}
void QuickSort(int *arr, int left, int right)
{

	if (left < right)
	{
		int n = postion(arr, left, right);
		QuickSort(arr, left, n - 1);
		QuickSort(arr, n+1, right);
	}
}
最后实现以下双指针的非递归版本,借助栈来控制每个分组代码如下:

void QuickSort(int *array, int  left, int right)
{
	stack<int> s;
	s.push(right);
	s.push(left);
	while (!s.empty())
	{
		int begin=s.top();
		s.pop();
		int end = s.top();
		s.pop();
		int n = postion(array, begin, end);
		if (begin < n - 1)
		{
			s.push(n - 1);
			s.push(begin);
		}
		if (end>n + 1)
		{
			s.push(end);
			s.push(n+1);
		}
	}
}

最后给出测试代码和测试结果:

void test()
{
	int array[] = { 4,2,6,4,9,5,3,2,1,0};
	int size = sizeof(array) / sizeof(*array);
	QuickSort(array, 0, size - 1);
	for (int i = 0; i<size; i++)
		cout << array[i] << " ";
	
}
测试结果
















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值