一.冒泡排序
1.原理
在快速排序之前,我们得了解一下拥有差不多思想的一个简单版的排序,冒泡排序(或起泡排序)。
在冒泡排序中,我们的思路类似于吐泡泡一样或者扔石头一样:从后往前,把最小(最大)的值移动到最前面(或最后面) ,直到所有元素都被排序后,这个序列就变得有序。
冒泡排序的时间复杂度为:
O
(
n
2
)
O(n^2)
O(n2)
2.排序过程
3.代码
这里举例一个把最大元素“沉”到最后的代码。
void BubbleSort(int arry[], int len)
{
int i, j, temp;
for (i = 0; i < len; ++i) // 一共要排的个数
{
for (j = 0; j < len - i - 1; ++j) // 从0开始到最后-1-i个元素
{
if (arry[j] > arry[j+1]) // 如果当前元素比后面元素大,则交换位置
{
temp = arry[j];
arry[j] = arry[j+1];
arry[j+1] = temp;
}
}
}
}
二.快速排序
1.原理
快速排序采用递归+冒泡排序的思想。其过程如下:
- 首先将待排序的顺序表的开始与结束标记为low,high指针,且在选[low,high]取一个位置的值,作为枢轴(或支点)(pivotkey)。
- 从high开始(包括high)向前寻找,寻找小于(或大于)枢轴的值,并将该值与枢轴交换位置。
- 从low开始(包括low)向后寻找,寻找小于(或大于)枢轴的值,并将该值与枢轴交换位置。
- 重复2、3,直到
high==low
或low==high
的时候,此时枢轴的位置就是最终位置,且枢轴左边均小于枢轴,右边均大于枢轴。 - 将枢轴左右两边的两块儿,进行递归
1234
的操作。最后该数组即可完成排序
2.排序过程
然后我们对新序列1进行递归快排:
此时原数组已经成了为:
由于是递归表达式,所以我们递归栈应该会对新序列3开始排序:
此时数组状态为:
然后是新序列5:
数组状态:
然后递归栈来到了新序列4:
然后新序列6:
最后再返回到最开始入栈的新序列2:
所以,总的流程图为:
3.性能分析
推导式暂时不看,只记结论:
T
a
v
g
(
n
)
<
(
b
2
+
2
c
)
(
n
+
1
)
l
n
(
n
+
1
)
n
≥
2
T_{avg}(n) < (\frac{b} {2}+2c)(n+1)ln(n+1)\ \ \ n≥ 2
Tavg(n)<(2b+2c)(n+1)ln(n+1) n≥2,其中b c
是常数,那么我们的时间复杂度为:O(nlogn)
数量级的。平均和最好的时间复杂度为nlog2n,最坏情况下的时间复杂度为n2。空间复杂度可以优化到:log2n。
如果对枢轴的选取采用其他方法的话,可以大大改善在最坏情况下的排序的性能。
或者在一次划分
时进行优化,也可以改善最坏情况的性能。
但是这里不进行讨论了。
4.代码
代码我就懒得自己写了,抄一个:
#include <stdio.h>
void quickSort(int arr[], int low, int high)
{
int first = low;
int last = high;
int key = arr[first];
if(low >= high)
return;
while(first < last)
{
while(first < last && arr[last] > key)
{
last--;
}
arr[first] = arr[last];
while(first < last && arr[first] < key)
{
first++;
}
arr[last] = arr[first];
}
arr[first] = key;
quickSort(arr, low, first-1);
quickSort(arr, first+1, high);
}
int main()
{
int i;
int a[10] = {3, 1, 11, 5, 8, 2, 0, 9, 13, 81};
for(i = 0; i < 10; i++)
printf("%d ", a[i]);
printf("\n");
quickSort(a, 0, 9);
for(i = 0; i < 10; i++)
printf("%d ", a[i]);
printf("\n");
return 0;
}