7-快速排序

快速排序

快速排序是在实际中最常用的一种排序算法,速度快,效率高。就像名字一样,快速排序是最优秀的一种排序算法。

思想 快速排序采用的思想是分治思想。Portition

快速排序是找出一个元素(理论上可以随便找一个)作为基准(pivot),然后对数组进行分区操作,使基准左边元素的值都不大于基准值,基准右边的元素值 都不小于基准值,  

如此作为基准的元素调整到排序后的正确位置。

递归快速排序,将其他n-1 个元素也调整到排序后的正确位置。最后每个元素都是在排序后的正确位置,排序完成。

所以快速排序算法的核心算法是分区操作,即如何调整基准的位置以及调整返回基准的最终位置以便分治递归.

#include <iostream>
using namespace std;
int Portition(int a[], int low, int high)
{
	 int temp = a[low];
	while(low<high)
	{
		while(low<high && a[high]>=temp)
		{
			high--;
		}
		int aa = a[low];
		a[low] = a[high];
		a[high] = aa;
		while(low<high && a[low]<= temp)
		{
			low++;
		}
		aa = a[low];
		a[low] = a[high];
		a[high] = aa;
	}
	return low;
}
void QSort(int a[], int low, int high)
{
	if(low<high)
	{
		int temp =Portition(a, low, high) ;
		QSort(a,low,temp-1);
		QSort(a,temp+1,high);
	}
}
void QuickSort(int a[], int n)
{
	QSort(a, 0, n-1);
}
int main()
{
	int a[9]={5,1,9,3,7,4,8,6,2};
	cout<<"before sort:";
	for(int i=0;i<9;i++)
	{
		cout<<a[i]<<" ";
	}
	cout<<endl; QuickSort(a,9); //nlogn no
	cout<<"after sort:";
	for(int i=0;i<9;i++)
	{   
		cout<<a[i]<<" ";   
	}
	cout<<endl;
	return 0;
}
关于快速排序的优化

1. 优化选取的枢轴尽量将我们选取的数值  为中间点 

int Portition(int a[],int low, int high)
{
	if(a[low]>a[high])//优化选取的枢纽
	{
		swap(a,low,high)//low high  数值交换
	}
	if(a[mid]>a[high])
	{
		swap(a,mid,high)//mid high  数值交换
	}
	if(a[mid]>a[low])
	{
		swap(a,mid,low)//mid low  数值交换
	}
	int temp = a[low];
	while(low<high)
	{
		while(low<high && a[high]>=temp)
	{
		high--;
	}
		int aa = a[low];
		a[low] = a[high];
		a[high] = aa;
	while(low<high && a[low]<= temp)
	{
		low++;
	}
		aa = a[low];
		a[low] = a[high];
		a[high] = aa;
	}
	return low;
}
2. 优化在Protition 程序中不必要的 交换

int Portition(int a[], int low, int high)
{
	while(low<high)
	{
		while(low<high && a[high]>=temp)
		{
			high--;
		}
		a[low] = a[high];//优化
		while(low<high && a[low]<= temp)
		{
			low++;
		}
		a[high] = a[low]// 优化
	}
	a[low] = temp;//将temp 移动到最终目标位置
	return low;
}
3.优化小数组时候的排序方法  由于快排用到了递归因此 会有大量的函数调用,在处理小数据量排序时反而不如简单排序好。 

 意思就是说我可以在前半段用递归QSort处理大于7,后面用InsertSort 处理小型排序

#define MAX_Length_insertSort 7 或者 50
void QSort(int a[], int low, int high)
{
	if(high-low > MAX_Length_insertSort)
	{
		int temp =Portition(a, low, high);
		QSort(a,low,temp-1);
		QSort(a,temp+1,high);
	}
	else
	{
		ISort(a+low, high-low+1);
		//调用 直接插入就好了
	}
}
void ISort(int a[], int n)
{  
	//原来直接插入排序的内容
	for(int i=1;i<n;i++)
	{  
		if(a[i]<a[i-1])
		{
			int temp = a[i];
			int j = i-1;
			for(;j>=0 && temp<a[j];j--)
			{
				a[j+1] = a[j];  
			}
			a[j+1]=temp;
		}
	}
}
4. 优化递归操作 ,采用迭代 不是递归就缩减了堆栈的深度 函数循环调用的程度。 提高性能

快排函数在函数尾部有两次递归操作,我们可以对其使用尾递归优化

优点:if变成while 循环后第一次 QSort(a,low,temp-1)循环以后 变量low没用了

这时候我们将temp+1赋值给low  在while满足时执行Portition(a, low, high) 效果等效与QSort(a,temp+1,high);

void QSort(int a[], int low, int high)
{  
		while(low<high)
		{
			int temp =Portition(a, low, high) ;
			QSort(a,low,temp-1);
			// QSort(a,temp+1,high);=>low =temp+1;
			low =temp+1;
		} 
}
while (low < high)
{  
		pivot = Partition(list,low,high);
		if (pivot - low < high - pivot)
		{
			quicksort(list,low,pivot - 1);
			low = pivot + 1;
		}
		else  
		{
			quicksort(list,pivot + 1,high);
			high = pivot - 1;
		}  
}

优化5:在一次分割结束后,可以把与Key相等的元素聚在一起,继续下次分割时,不用再对与key相等元素分割

http://blog.csdn.net/hacker00011000/article/details/52176100

概括:这里效率最好的快排组合 是:三数取中+插排+聚集相等元素,它和STL中的Sort函数效率差不多

注意:由于测试数据不稳定,数据也仅仅反应大概的情况。如果时间上没有成倍的增加或减少,仅仅有小额变化的话,我们可以看成时间差不多.





posted @ 2017-03-24 10:47  sowhat1412  阅读(131)  评论(0编辑  收藏  举报