文章首发地址
三向分切快速排序(3-way Quicksort)是一种改进的快速排序算法,用于处理重复元素较多的情况。
传统的快速排序算法通常选择数组中的一个元素作为切分元素(pivot),并将数组划分为两个部分:比切分元素小的元素在左边,比切分元素大的元素在右边。然后对左右两部分分别进行递归排序。
但是当数组中有大量重复元素时,传统的快速排序算法性能会下降。因为在划分过程中,相同的元素会被分到不同的部分,导致重复元素的比较和交换次数增多。
三向分切快速排序则通过将数组划分为三个部分,避免了上述问题。具体来说,三向分切快速排序将数组划分为:
- 小于切分元素的部分;
- 等于切分元素的部分;
- 大于切分元素的部分。
然后对小于和大于切分元素的部分分别递归排序,等于切分元素的部分可以直接跳过,因为它们已经排好序了。
三行分切排序轨迹图:
三向分切快速排序的实现如下:
void quicksort(int[] arr, int left, int right) {
if (left >= right) {
return;
}
int pivot = arr[left];
int i = left + 1;
int lt = left; // 小于切分元素的部分的右边界
int gt = right; // 大于切分元素的部分的左边界
while (i <= gt) {
if (arr[i] < pivot) {
swap(arr, i++, lt++);
} else if (arr[i] > pivot) {
swap(arr, i, gt--);
} else {
i++;
}
}
quicksort(arr, left, lt - 1);
quicksort(arr, gt + 1, right);
}
void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
在上述代码中,lt和gt分别表示小于和大于切分元素的部分的边界。初始化时,它们分别为左右端点。i则用来扫描数组,将元素划分到相应的部分中。
具体来说,当扫描到的元素小于切分元素时,将它与小于部分的右边界交换,并将小于部分的右边界向右移动一位。当扫描到的元素大于切分元素时,将它与大于部分的左边界交换,并将大于部分的左边界向左移动一位。当扫描到的元素等于切分元素时,将i向右移动一位即可。
最后,递归地对小于和大于切分元素的部分进行排序即可。
三向分切快速排序在处理重复元素较多的情况下,比传统的快速排序算法具有更好的性能。但是它的空间复杂度为O(n),因为需要开辟额外的空间来存储等于切分元素的元素。