数据结构之排序--交换类排序

二  交换类排序

   基本思想是:两两比较待排序记录的关键字,发现两记录的次序相反时即进行交换,直到没有反序的记录为止!

1. 冒泡排序

    冒泡的原则:轻气泡不能在重气泡之下!

    如何进行?从下到上扫描待排记录,凡违反冒泡原则的轻气泡就向上“漂浮”。如此反复进行,直到任意两个气泡,都是轻者在上,重者在下!

void bubble_sort(int a[], int len)
{
    int i, j;

    for (i = 0; i < len - 1; i++) {
        for (j = 1; j < len - i; j++)  //这是从前向后冒,初始j = 1,以便用a[j-1].或者 (j = 0; j < len - i - 1; j++) a[j]与a[j+1]
            if (a[j - 1] > a[j]) {
                int tmp = a[j - 1]; 
                a[j - 1] = a[j];
                a[j] = tmp;
            }   
    }   
}

void bubble_sort(int a[], int len)
{
    int i, j;

    for (i = 0; i < len - 1; i++) {
        for (j = len - 1; j > 0; j--)  // 从后向前冒,(从下向上冒泡)
            if (a[j] < a[j - 1]) {
                int tmp = a[j];
                a[j] = a[j - 1]; 
                a[j - 1] = tmp;
            }   
    }   
}
注:注意下内层循环的边界问题即可



2. 快速排序

快速排序采用“分治法”,即将原问题划分为若干个规模更小,但结构与原问题相似的子问题!递归的解决这些子问题,然后将这些子问题的解组合为原问题的解!

a>划分,从待排数列中选择一个元素作为“基准zhi”,把“基准zhi”放到合适的位置,使在“基准zhi”前面的元素都比其小,在其后面的元素都比其大。基准zhi无需参加后续的排序!

b>求解,对前后子区间进行“快速排序”。

c>组合,每一次求解后都得到一个“基准zhi”,大小是按顺序来的。

具体如何划分呢?把第一个元素选作“基准zhi”。剩下的元素先于“基准zhi”相比较,并且进行移动,得到一个位置,使得在这个位置(fenjieweizhi)前的元素(基准除外),比基准小,之后的元素比基准大,然后把这个位置的元素和基准交换即可!

#define SWAP(a, b) \
    do {typeof(a) tmp; tmp = (a); (a) = (b); (b) = tmp;}while(0)

void quick_sort(int data[], int left, int right)
{
    int p = left;
    int i;

    if (left > right)
        return ;

    for (i = left + 1; i <= right; i++) {
        if (data[i] < data[left]) {
            p++;
            SWAP(data[i], data[p]);     // 此处改成SWAP(data[i], data[++p]),结果出错
        }
    }
    SWAP(data[left], data[p]);
    quick_sort(data, left, p - 1);
    quick_sort(data, p + 1, right);

    return ;
}

void quick_sorting(int a[], int len)
{
    quick_sort(a, 0, len - 1);
}

注: 1.颠倒quick_sorting 和 quick_sort的顺序,会报警告warning: conflicting types for ‘quick_sort’ [enabled by default] ,(当编译器没有找到函数声明时,默认函数返回值为int)

        2.快速排序经典写法(http://hi.baidu.com/gropefor/item/5d6c7312cc2022041894ecb9


       3. 快速排序的最好时间复杂度O(nlgn), 每次取的基准都相当于一个中间值,划分后基准两边元素大致相等,这样划分次数少,比较次数也少

            最坏时间复杂度O(n^2), 每次划分取的基准都是无序区中最大的或最小的,划分的结果是基准的一边是空,另一边仅比划分前的无序区少一个元素!(这样要做(n-1)划分)                             所以待排数列有序时,快速排序比较的次数最多


二.

void quick_sort(int a[], int left, int right)
{
    int l = left, r = right;
    int p = a[left];

    if (l > r) 
        return ;

    while (l < r) {
        while (l < r && p <= a[r])
            r--;
        a[l] = a[r]; 

        while (l < r && p >= a[l])
            l++;
        a[r] = a[l]; 
    }

    a[l] = p;

    quick_sort(a, left, l - 1); 
    quick_sort(a, l + 1, right); 

    return ;
}


    if (l > r)   || if (l >= r)
        return ;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值