快速排序法
基本思想:通过一趟排序,将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,然后分别对这两部分记录再进行分割排序,重复执行,直到整个序列有序为止。
过程需要:
- low:待排序列中的首个元素的索引
- high:待排序列的最后一个元素的索引
- pivot:基准,序列中挑选出的一个作为标准参考的元素(这里让基准 = 待排序列中的首个元素)
- left,right:先备份待排序列中的首尾索引,用于分组之后的赋值
比如:一组序列从 low 到 high ,一趟排序分组之后,low和high的值都变了,而且low值等于high值,分开的两组中,第一组为 left 到 low-1,第二组为 low+1 到 right,因为此时low指向的值恰为基准,所以不再参与下次排序。
排序过程:
- 从最后面的元素开始查找,指针high指向最后一个元素
- 若有大于基准值的元素,则不处理,指针high向左移一位
- 若有小于基准值的元素,则将此元素(high指向的)与low指针所指向的元素交换
- 然后再排查左面low指针所指向的值
- 若有小于基准值的元素,则low指针右移
- 若有大于基准值的元素,则将此元素(low指向的)与high指针所指向的元素交换
- 重复上述过程,直到low指针与high指针重合或交叉,则完成一趟排序
然后递归执行分组之后的排序,重复上述过程
Python代码
def quick_sort(lists, low, high):
# 结束条件
if low >= high:
return
# 让 基准 = 待排序列表中的第一个数
pivot = lists[low]
# 将待排序列表中两头的值先备份,用于下面递归时的赋值
left = low
right = high
while low < high:
# 查找右面第一个小于pivot的数,进行交换
while low < high and pivot <= lists[high]:
high -= 1
lists[low], lists[high] = lists[high], lists[low]
# 查找左面第一个大于pivot的数,进行交换
while low < high and pivot >= lists[low]:
low += 1
lists[low], lists[high] = lists[high], lists[low]
# 左面的一组,再进行上面的操作
quick_sort(lists, left, low - 1)
# 右面的一组,再进行上面的操作
quick_sort(lists, low + 1, right)
return lists
if __name__ == '__main__':
array = [5, 2, 0, 1, 3, 1, 4, 12, 9, 3, 15]
print(array)
quick_sort(array, 0, len(array) - 1)
print(array)
Java代码
package algorithm;
public class Sort {
// 快速排序算法
private static void quickSort(int[] array, int low, int high) {
if (low >= high) {
return;
}
// 每次基准都等于待排序列的第一个元素
int pivot = array[low];
int left = low;
int right = high;
// 进行一趟排序,并分组
while (low < high) {
// 在右面查找第一个小于基准的数
while (low < high && pivot <= array[high]) {
high -= 1;
}
// 然后进行交换
int temp = array[high];
array[high] = array[low];
array[low] = temp;
// 在左面找到第一个大于基准的数
while (low < high && pivot >= array[low]) {
low += 1;
}
// 然后进行交换
int temps = array[high];
array[high] = array[low];
array[low] = temps;
}
// 一趟结束之后,应该是low = high
// 然后以这个位置为分界线,把待排序列分成了两组
// 对左面的一组,再进行上述操作
quickSort(array, left, low - 1);
// 对右面的一组,再进行上述操作
quickSort(array, low + 1, right);
}
public static void main(String[] args) {
int[] array = new int[]{5, 2, 0, 1, 3, 1, 4};
Sort.quickSort(array, 0, array.length - 1);
// 打印数组
for (int i = 0 ; i < array.length ; i++) {
System.out.print(array[i] + " ");
}
}
}
时间复杂度:
最好情况:每次总是选到中间值作为基准,T(n) = O(nlog₂n)
最坏情况:每次总是选到最大或最小值作为基准,T(n) = O(n²)
平均情况:T(n) = O(nlog₂n),是所有同数量级的排序算法中最好的一种