LeetCode912——sort an array—— quick sort algorithm

这就是一道简单的数组排序问题,借这道题回顾和复习一下快速排序算法的实现。
快速排序被普遍认为是当下速度最快的排序算法之一,在处理大规模数据时其性能表现一般很好。然而,快速排序算法是输入敏感的(Input-Sensitive)算法,也就是其实际执行的耗时和输入序列的情况密切相关,也和我们找到的划分点Pivot在序列中排序之后的实际位置有关。

快速排序算法的思想很简单,也就是在待排序序列中按一定策略找出一个划分点元素Pivot,将比Pivot小的元素排列在Pivot左边比Pivot大的元素排在Pivot右边。再在左右两个子序列递归执行此算法(典型的减而治之算法策略),当退化到子序列长度为1时退出,这时整个序列全部有序。
在这里插入图片描述
如果每次我们都能确保取到的Pivot处于序列中的接近中间的大小位置,那么算法的性能能达到最优,可惜在无序序列中很难做到这一点。但是注意,Pivot的选择策略在某种程度上决定了这个算法的性能,常见的取Pivot的形式有:

// 1.直接取第一个元素作为Pivot
int Pivot = seq[0];

// 2.取序列中心元素为Pivot
int Pivot = seq[seq.size() / 2];

// 3.随机生成一个有效范围内的索引值,这样在统计意义上保证性能不会太差,有效索引区间是[Begin, End]
// 但是这样做每次算法的表现都会是一个不确定的情况,可能很好,可能不太好
int RandomIndex = (1.0 * rand() / RAND_MAX) * (End - Begin + 1) + Begin;
int Pivot = seq[RandomIndex]; 

下面是对算法的一个具体实现,首先是按照一定策略取Pivot并按此Pivot划分序列:

int getPivot(vector<int>& nums, int Begin, int End)
    {
    
    
        // generate a random index in intervel [Begin, End]
        /*3 different strategies*/
        int RandomIndex = (1.0 * rand() / RAND_MAX) * (End - Begin + 1) + Begin; 
        // int RandomIndex = (Begin + End) / 2;
        // int RandomIndex = 0;

        // storing the temporary variable
        int Pivot = nums[RandomIndex];

        // swap the Pivot with nums[Begin], so we need to start from End to fill the Begin
        swap(nums[Begin], nums[RandomIndex]); 

        // loop until Begin == End
        while(Begin < End)
        {
    
    
            // find the first element which is < Pivot
            while(Begin < End && nums[End] >= Pivot) 
                --End;
            nums[Begin] = nums[End];

            // symmetrical to above situation
            while(Begin < End && nums[Begin] < Pivot)
                ++Begin;
            nums[End] = nums[Begin];
        }
        // assert (Begin == End);
        // put the Pivot in nums[Begin](nums[End])
        nums[Begin] = Pivot;
        return Begin;
    }

注意上面的代码中,如果我们选取的Pivot不是nums[0],我们就将它和nums[Begin]做一个交换,这样是为了保证我们的序列遍历从两端开始进行。也正因为此,我们的第一个while循环

	// find the first element which is < Pivot
  	while(Begin < End && nums[End] >= Pivot) 
    	--End;
    nums[Begin] = nums[End];

从序列的尾部开始向开头搜索(因为这时候nums[Begin]存储的就是Pivot,而Pivot已经被记录到变量Pivot中,所以此位置可覆盖)。这个函数实现了Pivot的选取和基于Pivot的序列划分,返回值是Pivot最终插入的位置
然后,我们递归的对左右两侧进行同样的操作,注意递归基(我取的是闭区间[Begin, End]):

 	void quickSort(vector<int>& nums, int Begin, int End)
    {
    
    
        if(Begin >= End)
            return;
    
        // get the Pivot of nums
        int Pivot = getPivot(nums, Begin, End);

        // sort the Begin & End subsequence recursively
        quickSort(nums, Begin, Pivot - 1);
        quickSort(nums, Pivot + 1, End);
    }

这就是完整的快速排序QuickSort算法,最终在主函数中调用之即可:

		vector<int> sortArray(vector<int>& nums) {
    
    
        // generate a random seed
        srand((int)time(NULL));
        quickSort(nums, 0, nums.size() - 1);
        
        return nums;
    }

Guess you like

Origin blog.csdn.net/zzy980511/article/details/116132819