快速排序quicksort的核心是对无序向量进行快速划分,选取一个元素作为轴点(pivot)对向量进行划分,确保比轴点大的元素在轴点之后,比轴点小的元素在轴点之前,将原向量划分为两个子向量。
算法思想:
- 取一元素为轴点(pivot),不妨取首元素为轴点,并将轴点的值备份;
- 从向量的起始(low)和末尾(high)同时进行扫描;
- 若nums[high] < pivot, 将其换到nums[low];若nums[low] > pivot,将其换到nums[high];
- 当low与high位置重合后,将备份的pivot值填回nums[low].
int partition(vector<int>& nums, int low, int high) { // 任取一元素与首元素交换,以交换后的首元素作为基准 int r = low + rand() % (high - low + 1); int tmp = nums[low]; nums[low] = nums[r]; nums[r] = tmp; int pivot = nums[low]; // 由向量两端向中部扫描 while (low < high) { while (low < high && pivot <= nums[high]) high--; nums[low] = nums[high]; while (low < high && pivot >= nums[low]) low++; nums[high] = nums[low]; } nums[low] = pivot; return low; }
上述partition算法返回轴点nums向量中的位置.
显然,该划分算法的时间复杂度是O(n)O(n),空间复杂度为O(1)O(1).
三划分(3-way-partition)
有些时候需要将向量快速划分为三块,例如LeetCode Sort Colors,向量nums中的元素等于0或1或2,要求在排序后,所有的0在最前面,然后是所有的1,最后是所有的2.该问题可以用三划分方法来解决。
与上述的划分算法相同,分别从向量的首尾开始扫描,同时从向量的左侧向右侧扫描,若nums[i] == 0, 则与nums[low]交换,并且low++,i++;若nums[i] == 1, i++;若nums[i] == 2, 则与nums[high]交换,并且high–,注意此时i并不增加。
// 3-way partition void sortColors(vector<int>& nums) { if (nums.empty()) return; int i = 0, low = 0, high = nums.size() - 1; while (i <= high) { if (nums[i] == 1) i++; else if (nums[i] == 0) swap(nums[i++], nums[low++]); else swap(nums[i], nums[high--]);// not i++ } }
————————————————
版权声明:本文为CSDN博主「zhusf16」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012604810/article/details/80838497