zoukankan      html  css  js  c++  java
  • 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函数效率差不多

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





    关注公众号 海量干货等你
  • 相关阅读:
    「NOTE」支配树
    「SOL」支配 (2021省选A卷)
    「SOL」矩阵游戏 (2021省选A卷)
    「SOL」最差记者2 (LOJ / JOISC2016)
    「SOL」Nondivisible Prefix Sums(AtCoder)
    「SOL」Spaceship(LOJ/USACO)
    「NOTE」可持久化非旋Treap
    「SOL」事情的相似度(LOJ)
    FTP(File Transfer Protocol)——文件传输协议详解
    DHCP(Dynamic Host Configutation Protocol)——动态主机配置协议详解
  • 原文地址:https://www.cnblogs.com/sowhat1412/p/12734468.html
Copyright © 2011-2022 走看看