快速排序的几种优化

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">快速排序是交换排序的一种。其主要过程为:</span>

1.在一组数中选取一个key

2.将大于key的放到一边,小于key的放到另一边

3.分区,重复上两步


快速排序最易理解算法1:

1.将最右边的数选为key

2.begin和end分别为左下标和右下标

3.从begin向后,找到比key大的数停下来;从end向前找,找到比key小的数停下来

4.交换begin和end指向的值

5.从key分区,继续重复过程1、2、3、4。

int partition(int *a, int left, int right)
{
<span style="white-space:pre">	</span>int key = a[right];
<span style="white-space:pre">	</span>int begin = left;
<span style="white-space:pre">	</span>int end = right - 1;
<span style="white-space:pre">	</span>while (begin < end)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>while (a[begin] < key)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>++begin;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>while (begin < end&&a[end]>key)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>--end;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>if (begin < end)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>swap(a[begin], a[end]);
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>if (a[begin]>a[right])
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>swap(a[begin], a[right]);
<span style="white-space:pre">		</span>return begin;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>else
<span style="white-space:pre">		</span>return right;
}
void QuickSort(int *a, int left,int right)
{
<span style="white-space:pre">	</span>assert(a);
<span style="white-space:pre">	</span>if (left < right)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>int div = partition(a, 0, right);
<span style="white-space:pre">		</span>QuickSort(a, 0, div - 1);
<span style="white-space:pre">		</span>QuickSort(a, div + 1, right);
<span style="white-space:pre">	</span>}
}

快速排序优化之挖坑法

1.选取最右边的数a[right]为“坑”,同时选取最右边的数为key,左下标为begin,右下标为end

2.从begin开始找大于key的数,找到后,将这个数填到“坑”中,即a[end],填好后,end--,a[begin]为新"坑"

3.从end向前找比key小的数,找到后,将这个数填到“坑”中,即a[begin],填好后,begin++,a[end]为新“坑”

4.当begin=end时,这个坑就是,a[begin],用key填进去

5.以key为分区,在每个分区重复1、2、3、4

int partition(int *a, int left, int right)
{
	int key = a[right];
	int begin = left;
	int end = right;
	while (begin < end)
	{
		while (begin<end&&a[begin] <= key)
		{
			begin++;
		}
		if (begin < end)
		{
			a[end] = a[begin];
			end--;
		}  
		while (begin<end&&a[end]>key)
			--end;
		if (begin < end)
		{
			a[begin] = a[end];
			begin++;
		}
	}
	a[begin] = key;
	return begin;
}
void QuickSort(int *a, int left,int right)
{
	assert(a);
	if (left < right)
	{
		int div = partition(a, 0, right);
		QuickSort(a, 0, div - 1);
		QuickSort(a, div + 1, right);
	}
}
优化三数取中法

由于快速排序在key取到接近最大或者接近最小的值时是快速排序的最坏情况,所以,在取key时,比较a[right],a[left],a[mid]的值后,取中间的数作为key时间效率最好

void GetMid(int *a,int left,int right)//将中间的值换到right的位置上
{
	if (left<right)
	{
		int mid = left + ((right - left) >> 1);

		if (a[mid] > a[left])//arr[mid]<=a[left]
		{
			swap(a[mid], a[left]);
		}
		if (a[right] > a[left])//a[right]<=a[left]
		{
			swap(a[left], a[right]);
		}
		if (a[mid]>a[right])//a[mid]<=a[right]
		{
			swap(a[mid], a[right]);
		}
	}
	
	return ;
	//a[mid]<=a[right]<=a[left]
}


优化

除了三数取中的方法优化外,还有另一种方法:

1.设置一个cur和prev

2.prev始终在cur的前一个或者比key大的前一个

这种方法可以用于链表的快速排序

int partition(int *a, int left, int right)
{
	//prev指向cur前一个或者比key大的前一个
	int key = a[right];
	int prev = left - 1;
	int cur = left;

	while (cur < right)
	{
		if (a[cur] <= key&&++prev != cur)
			swap(a[prev], a[cur]);
		++cur;
	}
	swap(a[++prev], a[right]);
	return prev;
}
void QuickSort(int *a, int left,int right)
{
	assert(a);
	if (left < right)
	{
		int div = partition(a, 0, right);
		QuickSort(a, 0, div - 1);
		QuickSort(a, div + 1, right);
	}
}


优化
若遇到很多数的时候想使用快速排序,则先使用快排,当划分的区间较小的时候,使用插入排序

void QuickSort(int *a, int left, int right)
{
	if ((right - left) < N)//N表示一个常数
	{
		InsetSort(a + left, right - left + 1);//插入排序
	}
	else
	{
		int div = partition(a, 0, right);//快速排序
		QuickSort(a, 0, div - 1);
		QuickSort(a, div + 1, right);
	}

}


快速排序的非递归实现

#include<stack>
void QuickSort(int *a, int left, int right)
{
	stack<int>s;
	s.push(left);
	s.push(right);

	while (!s.empty())
	{
		int end = s.top();
		s.pop();
		int begin = s.top();
		s.pop();

		int div = partition(a, begin, end);
		if (begin < div - 1)
		{
			s.push(begin);
			s.push(div - 1);
		}<pre name="code" class="cpp"><span style="white-space:pre">		</span>if (div + 1 < end)
		{
			s.push(div + 1);
			s.push(end);
		}
	}
}

 


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值