一、起泡排序
起泡排序是交换排序里面最简单的情况;
相当于直接插入排序之于插入排序。一趟起泡排序如下图

- 起泡排序算法
void BubbleSort(SqList L, int n)
{
i = n;
while(i>1)
{
lastExchangeIndex = 1;
for(j=1; j<i; j++)
{
if(L.r[j+1].key < L.r[j].key)
{
Swap(L.r[j], L.r[j+1]); //交换1次,内含3次移动
lastExchangeIndex = j;
}
}
i = lastExchangeIndex;
}
}
- 上面算法的
结束条件为:在一趟起泡排序中没有进行任何记录交换操作。 - 时间性能分析
最好的情况(关键字在记录序列中顺序有序):只需进行一趟起泡。比较次数:n-1。移动次数:0。
最坏的情况(关键字在记录序列中逆序有序):需进行 n-1 趟起泡。比较次数:(n-1)+…+1。移动次数:3 * (n-1 + … + 1)。
起泡排序的时间复杂度也是:O(n2),在交换排序里面算是时间复杂度比较高的。
二、一趟快速排序(改进起泡排序)
-
基本思想
对起泡排序的一种改进,通过一趟排序将待排记录分成独立的两部分,其中一部分记录的关键字均比另一个部分记录的关键字要小。
然后继续、分别对这两个部分记录以相同方式排序 (递归)… 最终使整个记录序列有序。 -
一轮的目标
找一个记录,以它的关键字作为 “枢轴”,凡其关键字小于枢轴的记录均移动至该记录之前,凡关键字大于枢轴的记录均移动至该记录之后,记录的无序序列 R[s … t] 分成两个部分:
R[s … i-1] 和 R[i+1 … t] ,且
R[j].key <= R[i].key <= R[j].key
( s <= j <= i-1 ) 枢轴 ( i+1 <= j <= t )

-
一趟选出枢轴并将序列一分为二的算法
int Partition(SqList &L, int low, int high)
{
L.r[0] = L.r[low];
pivotkey = L.r[low].key;
while(low < high)
{
while(low<high && L.r[high].key>=pivotkey)
{
high--;
}
L.r[low] = L.r[high];
while(low<high && L.r[low].key<=pivotkey)
{
low++;
}
L.r[high] = L.r[low];
}
L.r[low] = L.r[0]; //枢轴记录到位
return low;
}
三、快速排序
- 整个快速排序的过程可以通过递归进行一趟快速排序来实现。
void QSort(SqList &L, int low,int high)
{
//对顺序表L中的子序列L.r[low .. high] 作快速排序
if(low < high)
{
pivotloc = Partition(L, low, high);
QSort(L, low, pivotloc-1);
QSort(L, pivotloc+1, high);
}
}
void QuickSort(SqList &L)
{
QSort(L, 1, L.length);
}
四、快速排序的时间性能分析

一般情况下为 O(nlogn)
若待排序记录的初始状态按关键字有序,快速排序 退化为 起泡排序,时间复杂度为O(n2),划分成0,和 -1。(范围满了)只有取中间的时候才是最好的情况。

博客介绍了起泡排序、一趟快速排序(改进起泡排序)和快速排序。起泡排序简单但时间复杂度较高,最好情况只需一趟,最坏需n - 1趟。一趟快速排序通过枢轴将记录序列划分。快速排序通过递归一趟快速排序实现,一般时间复杂度为O(nlogn),初始有序时退化为O(n2)。

4万+

被折叠的 条评论
为什么被折叠?



