第七章#7.3交换排序

两两比较,如果发生逆序则交换,直到所有记录都排好序为止

常见的交换排序有两种:

  • 冒泡排序 O(n2)

  • 快速排序 O(nlog2n)

###冒泡排序###

每趟两两比较,前小后大

img

  • 有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
            }
        }
    }
}

###快速排序###

img

动图中,黄色是中心元素,绿色的是小于中心元素的,紫色的是大于中心元素的,红色的是遍历到的元素

 

//排序主函数
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;
}

 

 

  • 快速排序是一种不稳定的排序方法

  • 快速排序不适用于原本有序或基本有序的记录进行排序的情况

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值