快速排序算法

1、简介

  • 可以认为是性能最好的排序方法,数据规模越大快速排序的性能越优
  • 核心思想是分治

2、算法思路

Partition 划分

  • 快速排序中最重要的一个步骤是划分
  • 在待排续表L[1,...,n]中任取一个元素pivot作为基准,给基准数据找其正确索引位置
  • 划分后左边的元素都比pivot小,右边的元素都比pivot大,于是形成了两个子序列
  • 每一次划分能确定pivot在序列中的位置

划分实现思路

  1. 找到pivot PS: 这里有很多可以优化的地方,重要的是pivot不要选成最小
  2. 初始化low为划分部分第一个元素的位置,high为最后一个元素的位置
  3. high向前移动找到第一个比pivot小的元素,这里的先后顺序不能乱(根据pivot所在位置)
  4. low向后移动找到第一个比pivot大的元素
  5. 交换当前两个位置的元素
  6. 继续234的过程直到low>=high为止
  7. 此时low == high 就是pivot应该在的位置

3、代码实现

  • RandomInRange用于在序列中随机获取pivot,主要是应对一种极端情况(算法分析部分会讲)

    //随机选择Pivot的位置
    int RandomInRange(int low, int high) {
    	return  rand() % (high - low + 1) + low;
    }
    
    //将子序列按照Pivot划分为两个子序列
    template<class T> int Partition(T* array, int low, int high) {
    	//得到Pivot
    	int index = RandomInRange(low, high);  
    	T pivot = array[index];
    	//将Pivot移到子序列的首位,统一操作
    	array[index] = array[low];
    	array[low] = pivot;  
        
    	while (low < high) {
    		while (low < high && pivot <= array[high]) 
    			high--;  //从high开始向右找到第一个小于pivot的值
    		array[low] = array[high];
    		while (low < high && pivot >= array[low])
    			low++;  //从low开始向左找到第一个大于pivot的值
    		array[high] = array[low];
    	}
    	array[low] = pivot;  //此时high == low的位置就是pivot的位置
    	return low; //返回两个子序列的分界点
    }
    
    //快速排序
    template<class T>
    void QuickSort(T* array, int low, int high) {
    	if (low < high) {   //如果子序列长度不为1  
    		int index = Partition(array, low, high);//进行一次划分
    		//对pivot左右两个序列继续进行快速排序
    		QuickSort(array, low, index-1);
    		QuickSort(array, index +1, high);
    	}
    }
    

4、算法分析

  • 空间复杂度 :O(logn)
  • 时间复杂度:O(n*logn)
  • 最坏复杂度O(n^2),待排序序列本身就是一个有序的序列,或者说每次划分选取的pivot总是当前切分数组的最小值(这就是随机选取pivot的意义,也有其他的方法)
  • 不稳定:交换过程中可能会改变先后顺序

改进思路:

  • 选取pivot的方法
  • 先判断数组的大小,如果小于某个值的时候,就用插入排序,大于某个值就用快速排序
posted @ 2020-08-18 19:02  Awaiting  阅读(82)  评论(0)    收藏  举报