• 冒泡排序


    冒泡排序是一种交换排序,它的基本思想是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序为止

    稳定性:冒泡排序是稳定排序

    时间复杂度: 最好:O(n)   最差:O(n^2)  平均:O(n^2)

    辅助空间:O(1)

    以下的所有代码都要用到的swap函数在此给出

    /*实现swap功能*/
    void swap(int *a, int *b){
        *a ^= *b;
        *b ^= *a;
        *a ^= *b;
    }
    View Code

    下面先看一段最简单的排序代码,从严格意义上说,它不算是标准的冒泡排序算法,因为它不满足 “两两比较相邻记录” 的冒泡排序思想,它更应该是最简单的交换排序而已。

    交换排序的数组版本:

    /* 对顺序表作交换排序(冒泡排序初级版) --- 数组版*/
    void BubbleSort11(int *L, int n){
        //注意下标从0开始
        for (int i = 0; i < n - 1; ++i){
            for (int j = i + 1; j < n; ++j){
                if (L[j] < L[i]){
                    //其实是简单选择排序的记录位置改成了直接交换,因此此版本的冒泡排序是不稳定排序
                    swap(L + i, L + j); 
                }
            }//for(j)
        }//for(i)
    }
    View Code

    交换排序的指针版本:

    /* 对顺序表作交换排序(冒泡排序初级版) --- 指针版*/
    /* [head,tail)为左闭又开区间*/
    void BubbleSort12(int *head, int *tail){
        for (int* p = head; p < tail - 1; ++p){
            for (int* q = p + 1; q < tail; ++q){
                if (*q < *p){
                    swap(p, q);
                }
            }//for(q)
        }//for(p)
    }
    View Code

    接下来便是正宗的冒泡排序算法,由于冒泡排序既可以从前往后冒泡,又可以从后往前冒泡,于是实现了从前往后冒泡和从后往前冒泡的数组、指针共4种版本。

    /* 冒泡排序算法 --- 数组版(采用从后往前冒泡)*/
    void BubbleSort21(int *L, int n){
        for (int i = 0; i < n - 1; ++i){
            for (int j = n - 1; j > i; --j){
                if (L[j] < L[j - 1])
                    //若后者小于前者,前移
                    swap(L + j, L + j - 1);
            }//for(j)
        }//for(i)
    }
    View Code
    /* 冒泡排序算法 --- 数组版(采用从前往后冒泡)*/
    void BubbleSort22(int *L, int n){
        for (int i = n - 1; i > 0; --i){
            for (int j = 0; j < i; ++j){
                if (L[j] > L[j + 1]){
                    //若前者大于后者
                    swap(L + j, L + j + 1);
                }
            }//for(j)
        }//for(i)
    }
    View Code
    /* 冒泡排序算法 --- 指针版(采用从后往前冒泡)*/
    /* 同理,[head, tail)为左闭右开区间 */
    void BubbleSort23(int* head, int* tail){
        for (int *p = head; p < tail - 1; ++p){
            for (int *q = tail - 1; q > p; --q){
                if (*q < *(q - 1)){
                    //后者小于前者,小的往前冒泡
                    swap(q, q - 1);
                }
            }//for(q)
        }//for(p)
    }
    View Code
    /* 冒泡排序算法 --- 指针版(采用从前往前后冒泡)*/
    /* [head, tail)为左闭右开区间 */
    void BubbleSort24(int* head, int* tail){
        for (int* p = tail - 1; p > head; --p){
            for (int* q = head; q < p; ++q){
                if (*q > *(q + 1)){
                    //若前者大于后者,大的往后冒泡
                    swap(q, q + 1);
                }
            }//for(q)
        }//for(p)
    }
    View Code

    其实,以上的冒泡排序是可以优化的,如序列{2,1,3,4,5,6,7,8,9}只需交换第一、第二的关键字,别的都已经是正常的顺序。 因此第一次交换后,数据已经有序,此后的大量比较是多余的,那如何优化呢? 我们可以增加一个标记变量flag,用于标记序列是否已经有序,详见代码。

    改进冒泡排序算法之数组版,从后往前冒泡

    /* 改进的冒泡排序算法 --- 数组版(从后往前冒泡) */
    void BubbleSort31(int* L, int n){
        bool flag = true; //最开始是为了进入循环
        for (int i = 0; i < n - 1 && flag; ++i){
            flag = false; //初始化为false,若下面的循环未做更改,则数列已经有序,退出循环
            for (int j = n - 1; j > i; --j){
                if (L[j] < L[j - 1]){
                    //若后者小于前者,小的往前冒泡
                    swap(L + j, L + j - 1);
                    flag = true; //更好做标记
                }
            }//for(j)
        }//for(i)
    }
    View Code

    改进的冒泡排序算法之指针版,从前往后冒泡

    /* 改进冒泡排序 --- 指针版(从前往后冒泡)*/
    void BubbleSort32(int* head, int* tail){
        bool flag = true;
        for (int* p = tail - 1; p > head && flag; --p){
            flag = false; //若下面的循环没有交换,则已经是有序序列,退出循环
            for (int* q = head; q < p; ++q){
                if (*q > *(q + 1)){
                    //若前者大于后者,从后往前冒泡
                    swap(q, q + 1);
                    flag = true;
                }
            }//for(q)
        }//for(p)
    }
    View Code
  • 相关阅读:
    「SDOI2009」Bill的挑战
    「HAOI2011」Problem c
    HDU3530【STL/单调队列/RMQ】
    HDU2874【倍增、ST】
    POJ2955【区间DP】
    SPOJ375 Query on a tree 【倍增,在线】
    训练[2]-DFS
    Fighting For 2017 Season Contest 1
    POJ2796/DP/单调栈
    New Year Tree 【DFS序+线段树区间查询修改+二进制保存状态】
  • 原文地址:https://www.cnblogs.com/tommychok/p/5030950.html
Copyright © 2020-2023  润新知