快速排序

快速排序的递归实现:


typedef int Item;

#define key(A) (A)

#define less(A, B) (key(A)< key(B))

#define exch(A, B) { Item t = A; A = B; B = t; }

#define compexch(A, B) if(less(B, A)) exch(A, B)


int partition(Item a[], int l, int r)

{

    int i = l-1, j=r;

    Item v = a[r];

    

    for ( ;  ;  ) {

        

        while (less(a[++i], v)) ;

        while (less(v, a[--j]))

            if (j == l)

                break;

        exch(a[i], a[j]);

    }

    

    exch(a[i], a[r]);

    return i;

}


void quicksort(Item a[], int l, int r)

{

    int i;

    if (r<=l)

        return;

    

    i = partition(a, l, r);

    quicksort(a,l, i-1);

    quicksort(a,i+1, r);

}


非递归快速排序:

使用了一个显示的下推栈,通过向栈中压入参数和过程调用  不断的从栈中弹出参数来替代递归调用,这个过程走到栈为空。我们把两个子文件的较大者压入栈中来确保栈的最大深度为lgN。


#define push2(S, A, B) S.push(B); S.push(A);


void quicksort2(Item a[], int l, int r)

{

    int i;

    stack<int> s;


    push2(s, l, r);

    while (!s.empty()) {

        

        l = s.top(); s.pop();

        r = s.top(); s.pop();

        

        i = partition(a, l, r);

        if (i - 1 > r - i)

        {

            push2(s, l, i-1);

            push2(s, i+1, r);

        }

        else

        {

            push2(s, i+1, r);

            push2(s, l, i-1);

      }

    }

}


改进:

1 递归程序调用自身的许多小的子文件,忽略栈中找到的所有小于M的文件,这类文件使用插入排序来运行和直接将这些小文件合并差不多。

2 三者取中划分 不取最右边的元素作为划分值,而使用首元素,中间元素,尾元素的中间值作为划分元素,减少出现最坏情况的概率。

3 重复关键字的处理。把数组划分为三部分,比划分元素小的元素, 与划分元素相等的元素, 比划分元素大的元素。


重复关键字算法:


#define eq(A, B) (!less(A, B) && !(less(B, A)))


void quicksort3(Item a[], int l, int r)

{

    int i, j, k, p, q;

    Item v;

    

    if (r <= l) {

        return;

    }

    v = a[r];

    i = i - 1; j = r; p = i - 1; q = r;

    for (; ;) {

        

        while (less(a[++i], v)) ;

        while (less(v, a[--j])) if(j == l) break;

        if (i>=j) break;

        

        exch(a[i], a[j]);

        if (eq(a[i], v)) {

            

            p++;

            exch(a[p], a[i]);

        }

        if (eq(v, a[j])) {

            

            q--;

            exch(a[q], a[j]);

        }

    }

    exch(a[i], a[r]);

    j = i - 1; i = i+1;

    for (k = 1; k<p ; k++, j--) {

        

        exch(a[k], a[j]);

    }

    for (k = r-1; k>q ; k--, i++) {

        

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

    }

    

    quicksort(a, l, j);

    quicksort(a, i, r);

}


三种基本的排序:


选择排序算法:首先选出数组中最小的元素跟数组中第一个元素交换,然后找出次小的元素与数组中第二个元素交换。。。

void selection(Item a[], int l, int r)

{

    int i, j;

    for ( i = l; i<r; i++) {

        

        int min = i;

        for (j = i+1; j<r; j++)

            if (less(a[j], a[min])) min = j;

        exch(a[i], a[min]);

    }

}


插入排入:为了插入新数据,先将较大的元素一个一个向右移动,然后将新数据插入到空位中。



void inserttion(Item a[], int l, int r)

{

    int i;

    // 找出最小元素作为观察哨

    for (i = r; i>l; i--)

        compexch(a[i-1], a[i]);

    for (i = l+2; i<=r; i++) {

        

        int j = i;

        Item v = a[i];

        while (less(v, a[j-1])) {

            

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

            j--;

        }

        a[j] = v;

    }

}


冒泡排序:内部循环通过从右到左遍历元素,对连续的元素执行比较交换操作。


void bubble(Item a[], int l, int r)

{

    int i, j;

    for (i = l; i<r; i++) {

        for (j = r; j>i; j--) {

            compexch(a[j-1], a[j]);

        }

    }

}


希尔排序: 插入排序的扩展。每第h个元素产生一个排好序的文件。

步长序列是1 4 13 40 121 364 1093 的希尔算法:


void shellsort(Item a[], int l, int r)

{

    int i, j, h;

    // 先从最大的开始

    for (h = l; h<=(r-1)/9; h=3*h+1) ;

    for (; h>0; h/=3) {

        

        for (i = l+h; i<=r; i++) {

            

            j = i; Item v = a[i];

            while (j>=l+h && less(v, a[j-h])) {

                

                a[j] = a[j-h];

                j -= h;

            }

            a[j] = v;

        }

    }

}






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值