排序

以下程序均与sort进行一百万数据对拍十次(有误请告知)
选择排序
#include <bits/stdc++.h>
using namespace std;
#define ll int
const int INF = INT_MAX;/// int的极限值
const int maxn = 1e5+7;
int mine = -INF; /// int 里面的最小值
int M[maxn];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    {
        scanf("%d",M+i);/// 输入
    }
    for (int i=1;i<=n;++i)
    {
        int t = mine;
        int idx =-1;
        for (int j=1;j<=n-i+1;++j)/// 从后往前找到大的元素放到后一个位置 (不包含已经排好序的)
        ///  (n-i+1)| 已经排好序.......
        {
            if (M[j] > t)
            {
               t = M[j];
               idx  = j;
            }
        }
        ///cout<<t<<' '<<idx<<endl;
        swap(M[idx],M[n-i+1]);///交换第I大的值放到未排序的最后
    }
    for (int i=1;i<=n;++i)
    {
        printf("%d ",M[i]);
    }
    puts("");
    return 0;
}
希尔排序
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
int n;
int A[maxn];
void shell_sort()
{   
    /*
         希尔排序   区别于之前的插入排序  希尔排序就是在原来的基础之上   首先按照一定的间隔进行插入排序
         缩小间隔 然后使得数组相对有序 最后进行间隔为1 的插入排序 也就是最基础的插入排序  
    */
    for(int di = floor(n/2);di>=1;di = floor(di/2)) ///每次缩半  向上取整
    {
        for (int i=di+1;i<=n;++i)/// 间隔为di的插入排序
        {
           A[0] = A[i];
           if (A[i] < A[i-di])
           {   
               int j;
               for (j=i-di;j>0&&A[0]<A[j];j-=di)
               {
                    A[j+di] = A[j];
               }
                A[j+di] = A[0];
           }  
        } 
    }
    for (int i=1;i<=n;++i)
    {
        printf("%d ",A[i]);
    }
    puts("");
}

int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;++i)scanf("%d",A+i);
    shell_sort();
    return 0;
}
冒泡排序
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+4;
int M[maxn];
int main()
{
    int n;
    scanf("%d",&n);
    for (int i=1;i<=n;++i)
    {
        scanf("%d",M+i);
    }
    for (int i=1;i<=n-1;++i)
    {
        for (int j=1;j<=n-i+1;++j)
        {
            if (M[j]<M[j+1])
                swap(M[j],M[j+1]);/// 其实冒泡排序的方法跟选择排序的很类似
            /// 这里就是每次从n个中选出最大值 不就是两个两个比较选出最大值   
            ///  从n-1个数中选出次大值   然后这里的话就是把这个n-i+1个数里面的最大值往后移
            /// 但是这样每次都需要交换(交换是需要时间的)  所以选择排序就将这里优化了
            /// 直接找n-i+1里面的最大值 ,然后将他放在n-i+1的位置上交换一次就可以了
        }
    }
    for (int i=1;i<=n;++i)
    {
        printf("%d ",M[i]);
    }
    puts("");
    return 0;
}
快速排序
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
int M[maxn];
int n;
/*
    快速排序的思路就是找到一个中枢轴 然后将大于中枢轴的数往中枢轴后面放,否则放在他之前
    然后遍历所有的轴ok  (分治算法)

*/
void  quick_sort(int ll,int rr)
{
    if (ll>=rr) return ;
    int l =ll;
    int r =rr; 
    int t = M[ll];/// 直接以ll作为中枢轴,那么此时的l是空出来的  
    /// 此时的方法就是往两边丢数,最后产生的分界线放中枢轴
    while (l<r)
    {
        while ((l<r) && M[r] >= t) --r;///先从右往左丢  
        if (l<r)
        {
            M[l] = M[r];
            ++l;
        }
        while ((l<r) && M[l] <= t) ++l;///从左往右丢
        if (l<r)
        {
            M[r] = M[l];
            --r; 
        }
    }
    M[l] = t;/// 最后一定是l>=r  假设最后是从右往左丢,那么r的数值丢到l,l++, l == r
    ///  假设最后是从左往右丢  那么l的数值丢到r,--r  l==r   所以这里l r都可以
    quick_sort(ll,l-1);///继续丢他的左右子区间  直至区间长度为1 这样就每次将n长的区间做两半处理
    quick_sort(l+1,rr);
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;++i)
    {
        scanf("%d",M+i);
    }
    ///cout<<1<<endl;
    quick_sort(1,n);
    for (int i=1;i<=n;++i)
    {
        printf("%d ",M[i]);
    }
    puts("");
    return 0;
}
堆排序
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
int M[maxn];
int n;
/*
   堆排序的构造原理就是多棵二叉树的集合体  那么这棵二叉树满足 父亲节点大于(或者小于)所有的子根节点、
   这样就保证根节点一定大于(或者小于)这棵子树的任何元素
   然后这样构造的好处就是每次这棵树的总根就是最大(最小)值
   但是他只满足于局部最优  ,局部最优从下往上就能够造成整体最大
*/
int update_heap_sort(int s,int sum)/// 当前根节点   需要更新的长度
{
    int R = M[s];///最上面的那个根节点
    for (int j=2*s;j<=sum;j*=2)///首先比较当前根所在的根和两个子节点  j记录子树的编号 s记录当前这棵子树的根
    {
        if ((j+1)<=sum && M[j]<M[j+1]) ++j;///记录j的位置  看看是否存在右子树 如果要往右子树方向交换就++
        if (R > M[j]) break;///已经是最大的了就无须操作
        else 
        {
            M[s] = M[j];/// 先将大的数从子节点上升到根节点  
            s = j;/// 但是又要满足堆的条件 任意一个根节点都要大于两个子节点 所以要将刚刚交换的小数往下沉 继续更新
        }
    }
    M[s] = R;///现在的s已经移动到合适的位置,可以将原来被交换的数放到s根上
}
void heap_sort()
{
    for (int i=n/2;i>=1;--i)/// n/2代表就是最后一个节点n的根n/2
    {
        update_heap_sort(i,n);///对于所有的根节点  从下往上更新最大值
        /// 保证当前任意的根节点的数大于子节点
    }
    for (int k=n;k>1;--k)
    {
        swap(M[1],M[k]);/// M[1] 表示他是最大值 因为M[1]在更新堆的时候就是最大值了
        update_heap_sort(1,k-1);///最后的数值已经排好序了所以大根堆堆顶被移除就需要更新
    }
}

void out()
{
    for (int i=1;i<=n;++i)
    {
       printf("%d ",M[i]);
    }   
    puts("");
}

int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;++i) scanf("%d",M+i);
    heap_sort();
    out();
    return 0;
}
插入排序(数组)
/* 
   插入排序
   数组实现 
   将原来的数组划分为一个有序组和无序组  有序|无序  将无序数组的插入进有序数组就会使得无序变少有序增多
*/
#include <bits/stdc++.h>
using namespace std;
const int  maxn = 1e5;///10^5
int a[maxn];
int main()
{
    int n;
    cin>>n;
    for (int i=1;i<=n;++i)
    {
       cin>>a[i];
    }
    for (int i=2;i<=n;++i)///剩余的n-1个数组成的无序组  
    {
        a[0] = a[i];///将所有待选择的数放在第一位进行比较,因为之后的数字移动会挤占当前位置
        int j;
        for (j=i-1;i>=1;--j)///从后往前边比对边移动   此时是在有序组中给无序组新来的数据找位置
        {
            if (a[0]>=a[j])break;
            a[j+1] = a[j];
        }
        a[j+1] = a[0];///给i找到一个合适的位置进行插入
    }
    for (int i=1;i<=n;++i)
    {
       if (i!=n) printf("%d ",a[i]);
       else printf("%d\n",a[i]);
    }
    return 0;
}
插入排序(链表)
/*
   插入排序链表实现
*/
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
struct Node {
   struct Node *next;
   int idx;
};
int main()
{
    int n;
    scanf("%d",&n);
    Node *Head;
    Head  = (struct Node*)malloc(sizeof(struct Node));///   构建一个表头 ,储存一个空值 
    struct Node *p;
    p = Head;
    for (int i=1;i<=n;++i)
    {
        int x;
        scanf("%d",&x);
        struct Node *q;
        q = (struct Node*)malloc(sizeof(struct Node));
        q->idx = x;
        p->next = q;///不断的将新的q插入到p之后
        p = p->next;
    }
    p->next = NULL;/// 表尾为空
    if (Head->next)///存在第一个数据才排序
    {
        struct Node *p;
        p = Head->next->next;///记录下一个位置,防止被覆盖
        Head->next->next = NULL;///链表截断 一个有序组,一个无序组
        while (p)
        {
            struct Node *q = p->next;
            struct Node *t = Head;
            while (t->next&&p->idx>t->next->idx)t = t->next;///移动,从前往后依次比对
            p->next = t->next;///比对完成,完成插入
            t->next = p;
            p = q;
        }
    }
    for (struct Node *T=Head->next;T;T=T->next)
    {
        printf("%d ",T->idx);
    }
    return 0;
}
插入排序(静态链表)
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
int M[maxn];
int N[maxn];///变化之前的链数组
int W[maxn];///变化之后的链数组
int n;
/*
   插入排序的主要思路就是一个有序组和一个无序组   
   A1 | A2  A3  A4  A5   
   然后的话将右边的无序区的数组一个一个的插入左边的有序组
*/
void init()
{
    N[0] = 1;
    ///处理下边界,此处相当于表头节点
    for (int i=1;i<=n;++i)  N[i] = i+1;
    ///初始化  ,当前和下一个相连的下标就是当前下标+1
    N[n] = 0;
    ///链表最后就指向0   
}
/*
     静态链表
     M数据负责储存原始数据
     N数组相当于指针,指出下一个
     N[i]记录的是和i相连的下一个区块的下标
*/
void out(int x)
{
    if (x)
    {
      printf("%d ",M[x]);
      out(N[x]);
    }
}///  输出函数
int main()
{
    scanf("%d",&n);
    init();
    for (int i=1;i<=n;++i)
    {
      scanf("%d",M+i); 
      /// cout<< M[i]<<endl;
    }
    if (N[0])
    {
        int p = 2;
        N[1] = 0; ///类似于之前的链表,只不过相当于将next指针换成一个数组   首先将链表的头截断
        while (p)
        {
            int t = 0;
            int q = N[p];///  记录下p的下一个坐标 防止丢失
            while (N[t] && M[p]>M[N[t]]) t = N[t];/// 找到有序组中可以插入的位置  找到的就是可以插入的位置的(前面那个)
            N[p] = N[t]; /// 首先取代t,将t的后面的那一段接给p
            N[t] = p;/// t的下一个就是p
            p = q;///无序组中的下一个
        }
     }
     out(N[0]);///输出
     cout<<endl;
    
     return 0;
}
静态链表转有序数组
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
int M[maxn];
int N[maxn];///变化之前的链数组
int W[maxn];///变化之后的链数组
int n;
/*
   插入排序的主要思路就是一个有序组和一个无序组   
   A1 | A2  A3  A4  A5   
   然后的话将右边的无序区的数组一个一个的插入左边的有序组
*/
void init()
{
    N[0] = 1;
    ///处理下边界,此处相当于表头节点
    for (int i=1;i<=n;++i)  N[i] = i+1;
    ///初始化  ,当前和下一个相连的下标就是当前下标+1
    N[n] = 0;
    ///链表最后就指向0   
}
/*
     静态链表
     M数据负责储存原始数据
     N数组相当于指针,指出下一个
     N[i]记录的是和i相连的下一个区块的下标
*/
void out(int x)
{
    if (x)
    {
      printf("%d ",M[x]);
      out(N[x]);
    }
}///  输出函数
int main()
{
    scanf("%d",&n);
    init();
    for (int i=1;i<=n;++i)
    {
      scanf("%d",M+i); 
      /// cout<< M[i]<<endl;
    }
    if (N[0])
    {
        int p = 2;
        N[1] = 0; ///类似于之前的链表,只不过相当于将next指针换成一个数组   首先将链表的头截断
        while (p)
        {
            int t = 0;
            int q = N[p];///  记录下p的下一个坐标 防止丢失
            while (N[t] && M[p]>M[N[t]]) t = N[t];/// 找到有序组中可以插入的位置  找到的就是可以插入的位置的(前面那个)
            N[p] = N[t]; /// 首先取代t,将t的后面的那一段接给p
            N[t] = p;/// t的下一个就是p
            p = q;///无序组中的下一个
        }
     }
     
     ///out(N[0]);///输出
     ///cout<<endl;
     ///  之前的已经按照静态链表的数组进行储存
     ///  现在需要将数组变成有序数组  就不需要N数组的辅助
     for (int k=0;k<=n;++k)
     {
         W[k] = N[k];///  进行复制
     }
     int i = 1;
     int j = N[0];
     for (i = 1;i < n;++i)
     {
       ///cout<<i<<' '<<j<<endl;
       if (i==j)  ///  i是摆放的位置  j是摆放的数据来源的下标  相同就直接下一个
       {
         j = N[j];
       }
       else if(i<j) /// 如果当前的在后面 直接交换  已经摆好位置的i被后面的M[j]取代,
        ///  那么下次如果有之前的寻找的话,此时将W【i】变为J代表该位置已经被移动到j位置
       {
         swap(M[i],M[j]);
         W[j] = W[i];
         W[i] = j;
         j = N[j];  
       }
       else 
       {
          int t = j;/// j本身不能动,因为要从这里寻找下一个位置
          while (i>t) t=W[t];    ///  i>j 说明我现在需要交换的数据来源于之前的j,但是之前的位置按照w[t]一直寻找
          swap(M[i],M[t]);/// 跳到 i<j 的位置  然后进行交换   
          W[i] = t;  
          j = N[j];///  但是原本的位置还是需要保留   因为每次都是根据之前的原来的连接关系来求解的
       }
     }
     for (int t=1;t<=n;++t)
     {
       printf("%d ",M[t]);
     }
     puts("");
     return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值