排序算法

1.冒泡排序

•依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。至此第一趟结束,将最大的数放到了最后。在第二趟:仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再小于第2个数),将小数放前,大数放后,一直比较到倒数第二个数(倒数第一的位置上已经是最大的),第二趟结束,在倒数第二的位置上得到一个新的最大数(其实在整个数列中是第二大的数)。如此下去,重复以上过程,直至最终完成排序。
由于在排序过程中总是小数往前放,大数往后放,相当于气泡往上升,所以称作冒泡排序

template <typename T>

void bubble(T *a, int n) {

    for (int i = 0; i < n - 1; i++) {

        bool flag = true;

        for (int j = 0; j < n - i - 1; j++) {

            if (a[j]  > a[j+1]) {

                flag = false;

                swap(a[j], a[j+1]);

            }

        }

        if (flag) {

            break;

        }

    }

}





2.直接插入排序

•采用的是以 “玩桥牌者”的方法为基础的。即在考察记录Ri之前,设以前的所有记录R1, R2 ,…., Ri-1已排好序,然后将Ri插入到已排好序的诸记录的适当位置。
最基本的插入排序是直接插入排序(Straight Insertion Sort) 

•将待排序的记录Ri,插入到已排好序的记录表R1, R2 ,…., Ri-1中,得到一个新的、记录数增加1的有序表。 直到所有的记录都插入完为止。
•设待排序的记录顺序存放在数组R[1…n]中,在排序的某一时刻,将记录序列分成两部分:
–R[1…i-1]:已排好序的有序部分;
–R[i…n]:未排好序的无序部分。
显然,在刚开始排序时,R[1]是已经排好序的

•设有关键字序列为:7, 4, -2, 19, 13, 6,直接插入排序的过程如图

初始记录的关键字: [7]     4   -2    19    13   6

第一趟排序: [4    7]   -2    19    13    6

第二趟排序: [-2    4   7]     19    13   6

第三趟排序: [-2    4    7     19]    13   6

第四趟排序: [-2    4   7     13     19]   6

第五趟排序: [-2    4   6     7     13    19]


//插入

template <typename T>

void insert(T *a, int n) {

    for (int i = 1; i < n; i++) {

        int t = a[i]; //要插入的值

        int j;

        for (j = i; j > 0 && a[j - 1] > t; j--) {

            a[j] = a[j - 1];

        }

        a[j] = t;

    }

}




3.选择排序

每次从当前待排序的记录中选取关键字最小的记录表,然后与待排序的记录序列中的第一个记录进行交换,直到整个记录序列有序为止

初始记录的关键字: 7     4   -2    19    13   6

第一趟排序:-2     4    7     19     13   6

第二趟排序: -2     4    7     19    13   6

第三趟排序: -2     4    6     19   13    7

第四趟排序: -2    4    6     7     13    19

第五趟排序: -2    4    6    7     13    19

第六趟排序: -2    4    6    7     13    19

//选择

template <typename T>

void select(T *a, int n) {

    for (int i = 0; i < n - 1; i ++) {

        int k = i;//假设k是最小数的下标

        for (int j = i + 1; j < n; j++) {

            if (a[j] < a[k]) {

                k = j;

            }

        }

        if (k != i) {

            swap(a[k], a[i]);

        }

    }

}






4.快速排序

•是一类基于交换的排序,系统地交换反序的记录的偶对,直到不再有这样一来的偶对为止
•通过一趟排序,将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,再分别对这两部分记录进行下一趟排序,以达到整个序列有序。

//快速

template <typename T>

void qsort(T *a, int n) {

    if (n <= 1) return;

    int L = 0;

    int R = n - 1;

    //一次分组

    while (L < R) {

        while (L < R && a[L] <= a[R]) {

            R --;

        }

        swap(a[L], a[R]);

        while (L < R && a[L] <= a[R]) {

            L++;

        }

        swap(a[L], a[R]);

    }

    //对左边再次进行分组

    qsort(a, L);

    //对右边再次进行分组

    qsort(a + L + 1, n - L - 1);

}



template <typename T>

void qsort2(T *a, int n) {

    if (n < 1) return;

    int L = 0;

    int R = n -1;

    int M = a[L];

    

    while (L < R) {

        while (L < R && M <= a[R]) {

            R --;

        }

        a[L] = a[R];

        while (L < R && a[L] <= M) {

            L ++;

        }

        a[R] = a[L];

    }

    a[L] = M;

    

    //对左边进行分组

    qsort2(a, L);

    //对右边进行分组

    qsort2(a + L + 1, n - L - 1);

}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值