排序算法--补充

            对于上次学习借鉴到的大师级的排序算法,感概良多,从算法执行的效率上来说,quickSort()不考虑普遍的最环情况,它的速队的确是排序算法中的佼佼者。

       这次的学习到的算法包括了插入排序(直接插入,折半插入,希尔排序),选择排序(堆排序),都是各有利弊。

       基本的算法实现如下,因为递归使用的不是很好,同时为了方便阅读就直接进入非递归了。

#include <iostream>
using namespace std;
//插入排序
//直接插入排序
void sort2(int a[],int size)
{
    for(int i=1;i<size;i++)
    {
        int x=a[i];
        int j=i-1;
        while(x<a[j])
        {
            a[j+1]=a[j];
            j=j-1;//为了保证后面的比较,所以j进行了自减操作。由于原来的j的位置是空余的,但是j又进行了自减,所以在循环结束后对j进行+1操作
        }
        a[j+1]=x;
    }
    for(int i=0;i<size;i++)
        cout<<a[i]<<" ";
    cout<<endl;
}
//折半插入排序(时间复杂度最坏的情况是 O(n^2),最好的情况是o(nlgn))
void sort3(int a[],int size)
{
    for(int i=1;i<size;i++)
    {
        int x=a[i];
        int low=0,high=i-1;
        while(low<=high)
        {
            int mid=(low+high)/2;
            if(x<a[mid])
                high=mid-1;
            else
                low=mid+1;
        }
        for(int j=i-1;j>=low;j--)//在此,j要从开始插入中间值的时刻进行数组内的元素滞后,即要从插入之前定义的上限开始循环
            a[j+1]=a[j];
        a[low]=x;
    }
    for(int i=0;i<size;i++)
        cout<<a[i]<<" ";
    cout<<endl;
}
//希尔排序:将待排序纪录分割成若干的“较为稀疏”的子序列,在子序列中分别进行插入排序。分割的区间减小,然后再次进行上述的操作,最后在对全部的序列进行一次直接插入排序(即最后的分割区间的大小为1)。
//它类似于直接插入排序,但是优于直接插入排序,时间复杂度为o(n^1.5)。因为在插入排序的时候每一轮的改变只会减少一个逆转数(某个待排序纪录之前的序列大于它本身的纪录的个数,比如序列 8 6 9 3 5 7   对于5来说,它的逆转数为3,对于6来说它的逆转数为1),对于希尔排序每次的插入减少的逆转数不只一个。
//1.先进行一次排序
void sort4(int a[],int size,int delta)//dalta代表的是增量
{
    int i,j;
    for(i=1+delta;i<=size;i++)
        if(a[i]<a[i-delta])
        {
            a[0]=a[i];
            for(j=i-delta;j>0&&a[0]<a[j];j-=delta)
                a[j+delta]=a[j];
            a[j+delta]=a[0];
        }
}
//2.对增量进行重复输入
void sort4_1(int a[],int size,int delta[],int n)
{
    for(int i=0;i<n;i++)
        sort4(a, size, delta[i]);
    for(int i=0;i<size;i++)
        cout<<a[i]<<" ";
}
//堆排序(算法优点:减少了因为树形选择而占用的n-1个空间)
//由于堆排序的需要建立了一个结构体数组,实现的时候在主函数中输入需要排序的内容,使用a[i].data输入即可
//重建堆
struct Node{
    int data;
};
void sift(Node r[],int k,int m)//r[k...m]是以r[k]为根的完全二叉树,且分别以r[2k]和r[2k+1]为根的左右子树的大根堆
{
    Node t=r[k];
    int x=r[k].data;
    int i=k;
    int j=2*i;
    bool finished=false;
    while(j<=m&&!finished)
    {
        if(j<m&&r[j].data<r[j+1].data)
            j++;
        if(x>=r[j].data)
            finished=true;
        else
        {
            r[i]=r[j];
            i=j;
            j=2*i;
        }
    }
    r[i]=t;
}
//初建堆算法
void heap(Node a[],int size)
{
    int n=size,i;
    for(i=n/2;i>=1;i--)
        sift(a,i,n);
}
//堆排序
void sort5(Node a[],int n)
{
    heap(a,n);
    Node b;
    for(int i=n;i>=2;i--)
    {
        b=a[1];//将堆项纪录和堆中的最后一个纪录交换位置
        a[1]=a[i];
        a[i]=b;
        sift(a,1,i-1);//进行调整,使得a[1..i-1]变成堆
    }
}
int main(int argc, const char * argv[]) {
    int n;
    cin>>n;
    int num[n];
    for(int i=0;i<n;i++)
        cin>>num[i];
    cout<<"input delta"<<endl;
    int m;
    cin>>m;
    int delta[m];
    for(int j=0;j<m;j++)
        cin>>delta[j];
    sort1(num,n);
    sort3(num, n);
    sort4_1(num, n, delta, m);
    return 0;
}

    如果大家有更为高效的算法可以一起分享 吐舌头 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值