重温基础算法内部排序之快速排序法
Posted 顧棟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了重温基础算法内部排序之快速排序法相关的知识,希望对你有一定的参考价值。
内部排序之快速排序法
文章目录
对冒泡排序的一种优化
主要思想
快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。
通过一趟排序将待排记录分割成独立的两个部分,一部分的关键字比另一部分的关键字小,则可以分别对两部分记录继续进行排序。
- 选取任务选取的一个记录,作为枢轴或(支点)(pivot)
- 重新排列记录,所有关键字比pivot值小的摆放在pivot前面,所有关键字比pivot值大的摆在pivot的后面(相同的数可以到任一边)。在这个分区退出之后,该pivot就处于数列的中间位置。这个称为分区(partition)操作;
- 重复执行步骤2。把小于pivot关键字的子数列和大于pivot关键字的子数列排序。
过程演示
JAVA代码
package sort;
public class QuickSort
private static int count = 1;
public static void main(String[] args)
int[] o = 49, 38, 45, 27, 46, 13, 27, 8;
System.out.print("排序前: ");
for (int t : o)
System.out.print(t);
System.out.print(" ");
System.out.println();
// 算法部分
int left = 0;
int right = o.length - 1;
quickSort(o, left, right);
System.out.print("排序后: ");
for (int t : o)
System.out.print(t);
System.out.print(" ");
System.out.println();
private static void quickSort(int[] arr, int left, int right)
if (left < right)
int partitionIndex = partition(arr, left, right);
quickSort(arr, left, partitionIndex - 1);
quickSort(arr, partitionIndex + 1, right);
else
count++;
private static int partition(int[] arr, int left, int right)
// left位置的记录就是pivot,index代表比pivot小的下标
int index = left + 1;
System.out.print("第" + count + "趟pivot=" + arr[index - 1] + ",排序后: ");
for (int i = index; i <= right; i++)
if (arr[i] < arr[left])
swap(arr, i, index);
index++;
swap(arr, left, index - 1);
for (int t : arr)
System.out.print(t);
System.out.print(" ");
System.out.println();
count++;
return index - 1;
private static void swap(int[] arr, int i, int j)
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
执行结果
排序前: 49 38 45 27 46 13 27 8
第1趟pivot=49,排序后: 8 38 45 27 46 13 27 49
第2趟pivot=8,排序后: 8 38 45 27 46 13 27 49
第4趟pivot=38,排序后: 8 27 27 13 38 45 46 49
第5趟pivot=27,排序后: 8 13 27 27 38 45 46 49
第8趟pivot=45,排序后: 8 13 27 27 38 45 46 49
排序后: 8 13 27 27 38 45 46 49
算法分析
时间复杂度分析
经过上述一趟快速排序,我们只确定了一个元素的最终位置,我们最终需要经过 n n n趟快速排序才能将一个含有 n n n个数据元素的序列排好序,下面我们来分析其时间复杂度.
设
n
n
n 为待排序数组中的元素个数,
T
(
n
)
T(n)
T(n)为算法需要的时间复杂度则
T
(
n
)
=
D
(
1
)
n
≤
1
D
(
n
)
+
T
(
I
1
)
+
T
(
I
2
)
n
>
1
T(n)= \\begincases \\vcenter D(1) &n \\leq 1 \\\\ D(n)+T(I_1)+T(I_2) &n >1 \\endcases
T(n)=D(1)D(n)+T(I1)+T(I2)n≤1n>1
其中
D
(
n
)
=
n
−
1
D(n)=n−1
D(n)=n−1 ,是一趟快排需要的比较次数,一趟快排结束后将数组分成两部分
I
1
I_1
I1 和
I
2
I_2
I2。
最好时间复杂度
最好的情况是,每一次划分都正好将数组分成长度相等的两半
T
(
n
)
=
D
(
1
)
n
≤
1
D
(
n
)
+
T
(
n
2
)
+
T
(
n
2
)
n
>
1
T(n)= \\begincases D(1) & n \\leq 1 \\\\ D(n)+T(\\fracn2)+T(\\fracn2) &n >1 \\endcases
T(n)=D(1)D(n)+T(2n)+T(2n)n≤1n>1
∴
T
(
n
)
=
D
(
n
)
+
2
T
(
n
2
)
=
D
(
n
)
+
2
D
(
n
2
)
+
2
T
(
n
4
)
.
.
.
=
D
(
n
)
+
2
D
(
n
2
)
+
4
D
(
n
4
)
+
.
.
.
+
2
k
D
(
n
2
k
)
=
n
−
1
+
2
(
n
2
−
1
)
+
4
(
n
4
−
1
)
+
.
.
.
+
2
k
(
n
2
k
−
1
)
=
(
n
−
1
)
+
(
n
−
2
)
+
(
n
−
4
)
+
.
.
.
+
(
n
−
2
k
)
⟹
∑
k
=
1
n
n
−
2
k
=
k
n
−
2
k
+
1
∵
k
=
l
o
g
2
n
∴
原式
=
n
l
o
g
2
n
−
2
n
+
1
⟹
O
(
n
l
o
g
2
n
)
\\beginaligned \\therefore T(n)&=D(n)+2T(\\fracn2) \\\\ &=D(n)+2D(\\fracn2)+2T(\\fracn4) \\\\ &.\\\\ &.\\\\ &.\\\\ &=D(n)+2D(\\fracn2)+4D(\\fracn4)+...+2^kD(\\fracn2^k) \\\\ &=n-1+2(\\fracn2-1)+4(\\fracn4-1)+...+2^k(\\fracn2^k-1) \\\\ &=(n-1)+(n-2)+(n-4)+...+(n-2^k) \\\\ &\\implies \\displaystyle \\sum_k=1^n n-2^k=kn-2^k+1 \\\\ &\\because k=log_2^n\\\\ &\\therefore 原式=nlog_2^n-2n+1 \\implies \\boxedO(nlog_2^n)\\\\ \\endaligned
∴T(n)=D(n)+2T(2n)=D(n)+2D(2n)+2T(4n)...=D(n)+2D(2n)+4D(4n)+...+2kD(2kn)=n−1+2(2n−1)+4(4n−1)+...< 以上是关于重温基础算法内部排序之快速排序法的主要内容,如果未能解决你的问题,请参考以下文章