• 快速排序


    快速排序的基本思想是基于分治策略的,其算法思想如下:

    1.分解:先从数列中取出一个元素作为基准元素看,以基准元素为标准,

    将问题分解为两个子序列,使小于或等于基准元素的子序列在左侧,使大于基准元素的子序列在右侧。

    2.治理:对两个子序列进行快速排序。

    3.合并:将排好序的两个子序列合并在一起,得到原问题的解。

    (1)分解:

    选取第一个数作为pivot,设置两个指针low,high,意思即为R[low:high]

    指针从左开始扫描,若是R[low]<=pivot,则指针low右移,若遇到R[low]>pivot,R[low]的值和R[high]的值交换,

    同时,high指针向左移动,此时继续比较low指针与pivot大小关系。重复上述动作,这样一来,R[low]和pivot

    每比较一次就会有指针移动,要么是low右移要么是high左移,最终的结果一定是low和high重合。

    返回该位置mid=i;该位置正好是pivot元素。上代码:

    int partition(int r[],int low,int high)
    {
        int i=low,j=high,pivot=r[low];
    
        while(i<j)
            {
                if(r[i]<pivot)
                    i++;
                else
                    swap(r[i],r[j--]);
            }
        swap(r[low],r[j]);
        return j;
    }
     

    当然,还有另一种思路:

    int Partition(int r[],int low,int high) 
    {
    	int i=low,j=high,pivot=r[low];
    	while(i<j)
    	{
    		while(i<j&&r[j]>pivot)
    		{
    			j--;
    		}
    		if(i<j)
    		{
    			swap(r[i++],r[j]);
    		}
    		while(i<j&&r[i]<=pivot)
    		{
    			i++;
    		}
    		if(i<j)
    		{
    			swap(r[i],r[j--]);
    		}
    	}
    	return j;
    }

    两中方法结果是一样的。

    2.快速排序递归算法:

    首先对原序列执行划分,得到划分的中间位置mid,然后以中间位置为边界,分别对左半部分(low,high-1)执行快速排序,右半部分(mid+1,high)执行快速排序。递归条件是low>=high.

    void QuickSort (int R[],int low,int high)
    {
    	int mid;
    	if(low<high)
    	{
    		mid=Partition(R,low,high);//返回基准元素位置 
    		QuickSort(R,low,mid-1);//左区间递归快速排序 
    		QuickSort(R,mid+1,high);//右区间递归快速排序 
    	}
    }

    快速排序算法平均情况下,时间复杂度为O(nlogn),递归调用所使用的栈空间也是O(logn);

    优化算法:

    int Partition2(int r[],int low,int high) 
    {
    	int i=low,j=high,pivot=r[low];//基准元素
    	while(i<j) 
    	{
    		while(i<j&&r[j]>pivot) i--;//向左扫描
    		while(i<j&&p[i]<=pivot)  i++;//向右扫描
    		if(i<j) 
    		{
    			swap(r[i++],r[j--]); 
    		}
    	}
    	if(r[i]<pivot)
    	{
    		swap(r[i-1],r[low]);
    		return i-1;
    	}
    	swap(r[i],r[low]);
    		return i;
    }

    进一步优化:因为以上快速排序算法每次只能返回一个值,比如上一个算法返回的是i,那么如果一次返回多个值,会不会更快呢。

    public  int[] partition(int[] arr, int l, int r) {
    		int less = l - 1;
    		int more = r;
    		while (l < more) {
    			if (arr[l] < arr[r]) {
    				swap(arr, ++less, l++);
    			} else if (arr[l] > arr[r]) {
    				swap(arr, --more, l);
    			} else {
    				l++;
    			}
    		}
    		swap(arr[more],arr[r]);
    		return  int[] { less + 1, more };
    	}
  • 相关阅读:
    (转)Linux系统调用和库函数调用的区别
    一个“梦想实践重度障碍者”的思考
    按字节输出数据
    内存区划分、内存分配、常量存储区、堆、栈、自由存储区、全局区[C++][内存管理]
    VimdiffVIM的比较和合并工具
    [每天进步一点 流水账]回顾总结
    计算机就业方向
    ofstream和ifstream详细用法(转)
    ECMAScript 运算符关系运算符
    ECMAScript 语句标签语句
  • 原文地址:https://www.cnblogs.com/chmusk/p/11078922.html
Copyright © 2020-2023  润新知