两两比较,如果发生逆序则交换,直到所有记录都排好序为止
常见的交换排序有两种:
-
冒泡排序 O(n2)
-
快速排序 O(nlog2n)
###冒泡排序###
每趟两两比较,前小后大
-
有n个元素排序,则要冒泡n-1趟
-
每一趟冒泡都会把当前最重最大的沉到队尾
-
第一趟最大的沉到队尾,第二趟次大的沉到倒数第二个...,以此类推
-
第m趟要两两比较n-m趟,可以举例找找规律
//冒泡排序算法
void bubble_sort(SqList &L) {
int m, i, j; RedType x;//交换的临时中间储存变量
for (m=1; m<=n-1; m++) {//共需要n-1趟
for (j=1; j<=n-m; j++) {
if (L.r[j].key>L.r[j+1].key) {//发生逆序
x=L.r[j]; L.r[j]=L.r[j+1]; L.r[j+1]=x;//交换
}
}
}
}
-
优点:每趟结束时,不仅挤出一个最大值到最后,还能同时部分理顺其他元素
-
还能如何提高效率:一旦某一趟比较时不出现交换记录,说明从前到后两两之间都遵循顺序,即已经排好序了,就可以结束算法了
//改进版冒泡排序算法
void bubble_sort(SqList &L) {
int m, i, j; RedType x; flag=1;//交换的临时中间储存变量,flag作为是否有交换的标记
for (m=1; m<=n-1&&flag; m++) {//共需要n-1趟
flag=0;//重置这趟的flag为无交换状态
for (j=1; j<=n-m; j++) {
if (L.r[j].key>L.r[j+1].key) {//发生逆序
x=L.r[j]; L.r[j]=L.r[j+1]; L.r[j+1]=x;//交换
flag=1;//发生交换,flag置为1,若本趟没有发生交换,flag保持为0
}
}
}
}
###快速排序###
动图中,黄色是中心元素,绿色的是小于中心元素的,紫色的是大于中心元素的,红色的是遍历到的元素
//排序主函数
void main() {
QSort(L, 1, L.length);
}
//快速排序算法
void QSort(SqList &L, int low, int high) {
if (low<high) {//当前表长度大于1,low在high前面
pivotloc=Partition(L, low, high);
//将L.r[low...high]一分为二,pivtloc为中心元素排好的位置
QSort(L, low, pivotloc-1);
QSort(L, pivotloc+1, high);
}
}
//关键是如何找中心点位置,并且把表一分为二
int Partition(SqList &L, int low, int high) {
L.r[0]=L.r[low]; pivotkey=L.r[low].key;
while (low<high) {//low<high就是没有找到,只有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];
//里面这两个while要判断low<high
//因为搬动的过程low和high有移动,可能已经达到中心位置了
}//比中心元素小的都往前搬,比中心元素大的都往后搬
L.r[low]=L.r[0];//此时low和high重合,该位置就是中心位置
return low;
}
-
快速排序是一种不稳定的排序方法
-
快速排序不适用于原本有序或基本有序的记录进行排序的情况