C++八大排序算法(二)

紧接上次内容,把剩下四个排序算法贴上

快速排序

#include "iostream"
using namespace std;

int function(int a[],int left,int right) {
    int keyValue = a[left];       //每次把数组第一个元素设为标记值
    while (left < right) {
        while (left < right && a[right] >= keyValue)
            right--;
        a[left] = a[right];       //从右往左,把比标记值小的记录移到低端
        while (left < right && a[left] <= keyValue)
            left++;
        a[right] = a[left];       //从左往右,把比标记值大的记录移到高端
    }
    a[left] = keyValue;           //把标记值移到最后的空缺位
    return left;                  //返回标记值的索引
}

void sort(int a[],int left,int right) { 
    if (left < right) {
        int keyIndex = function(a,left,right);    //取到索引作为分界位
        sort(a,left,keyIndex-1);                  //索引左部递归排序
        sort(a,keyIndex+1,right);                 //索引右部递归排序
    }
}

int main() {
    int a[10] = {5,4,6,8,1,3,9,10,2,7};
    sort(a,0,9);
    for(int i = 0;i < 10;i++)
        cout<<a[i]<<" ";
    cout<<endl;
    return 0;
}

希尔排序

#include "iostream"
using namespace std;

void function(int a[],int n,int d) { 
    for(int i = d;i < n;i++) {              //从第一个子序列的第二个元素开始遍历
        if(a[i] < a[i-d]) {                 //当该元素小于有序序列的末元素时,进行插入排序
            int s = a[i];                   //标记该元素
            for(int j = i-d;j >= 0 && s < a[j] ;j -= d)     //从有序序列尾元素向前循环,标记元素查找插入位置,并移动其余元素
                a[j+d] = a[j];
            a[j+d] = s;                     //插入标记元素
        }
    }
}

void shell(int a[],int n) {
    int b[3] = {5,3,1};                 //增量序列,最后一个元素必须为1
    for(int i = 0;i < 3;i++) 
        function(a,n,b[i]);
}

int main() {
    int a[10] = {5,9,7,8,2,4,3,1,10,6};
    shell(a,10);
    for(int i = 0;i < 10;i++)
        cout<<a[i]<<" ";
    cout<<endl;
    return 0;
}

堆排序

#include "iostream"
using namespace std;

void function(int a[],int s,int m) {
    int i;
    int key = a[s];
    for(i = 2 * s;i <= m;i *= 2) {  //沿值较大的孩子结点向下筛选
        if(i < m && a[i] < a[i+1])  //i为值较大的记录的下标
            ++i;
        if(key > a[i])              //key应插入在位置s上
            break;
        a[s] = a[i];
        s = i;
    }
    a[s] = key;                     //插入
}

void heap(int a[],int n) {
    int i;
    for(i = n / 2;i > 0;--i)        //把a[1]~a[11]建成大顶堆 
        function(a,i,n);
    for(i = n;i > 1;--i) {  
        int s = a[1];               //将堆顶记录和当前未经排序子序列a[1]~a[i]中最后一个记录进行交换
        a[1] = a[i];
        a[i] = s;
        function(a,1,i-1);          //将a[1]~a[i-1]重新调整为大顶堆
    }
}

int main() {
    int a[11] = {0,2,5,6,7,9,1,3,10,4,8};//为了配合二叉树性质,左子树结点序号为父结点序号的两倍,故a[0]没有任何意义,待排序序列为a[1]~a[11]
    heap(a,10);
    for(int i = 1;i < 11;i++)
        cout<<a[i]<<" ";
    cout<<endl;
    return 0;
}

归并排序

#include "iostream"
using namespace std;

void function(int a[], int l, int m, int r) { 
    int n1 = m-l+1;
    int n2 = r-m;
    int *L = new int[n1];           //定义动态数组,长度为传入数组左部
    int *R = new int[n2];           //定义动态数组,长度为传入数组右部
    int i,j,k;

    for(i = 0;i < n1;i++)           //赋值左数组
        L[i] = a[l+i];
    for(j = 0;j < n2;j++)           //赋值右数组
        R[j] = a[m+j+1];

    for(i = 0,j = 0,k = l;i < n1 && j < n2 && k <= r;k++) {    //比较左数组和右数组元素大小,由小到大赋值给a
        if(L[i] < R[j]) 
            a[k] = L[i++];          
        else 
            a[k] = R[j++];
    }  
    if(i < n1) {                    //若左数组有剩余,则依次写到a数组尾部
        for(;k <= r;k++)
            a[k] = L[i++];
    }
    if(j < n2) {                    //若右数组有剩余,则依次写到a数组尾部
        for(;k <= r;k++)
            a[k] = R[j++];
    }

    delete []L;             //清除内存
    delete []R;
}  

void merge(int a[], int l, int r) {  
    if (l < r) {  
        int m = (l+r)/2;  
        merge(a, l, m);         //递归数组左部
        merge(a, m+1, r);       //递归数组右部
        function(a, l, m, r);   //归并排序
    }  
} 

void main() {
    int a[10] = {5,6,7,8,1,3,4,2,9,10};
    merge(a,0,9);
    for(int i = 0;i < 10;i++)
        cout<<a[i]<<" ";
    cout<<endl;
}

终。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值