zoukankan      html  css  js  c++  java
  • 排序

    洛谷一道模版题:https://www.luogu.org/problemnew/show/P1177

    归并排序(稳定排序)

    每次的操作只针对相邻区间(合并相邻区间),适合与很多数都有序的情况,这符合只需要修改相邻几个数的排布状况的情况,即使和快排的复杂度相同,但是省掉了冗杂无用的操作,是一个极大的改良。

     1 #include <iostream>
     2 #include <string>
     3 #include <algorithm>
     4 #include <iomanip>
     5 #include <cstdio>
     6 #include <cstring>
     7 using namespace std;
     8 const int maxn=1e5+5;
     9 int a[maxn],temp[maxn];
    10 int n;
    11 
    12 void MArray(int l,int mid,int r)
    13 {
    14     int i=l,j=mid+1;
    15     int k=0;
    16 
    17     while(i<=mid && j<=r)
    18     {
    19         if(a[i]<=a[j]) temp[k++]=a[i++];
    20         else temp[k++]=a[j++];
    21 
    22     }
    23     while(i<=mid) temp[k++]=a[i++];
    24     while(j<=r) temp[k++]=a[j++];
    25 
    26     for(int i=0;i<=k-1;i++) a[l+i]=temp[i];//更新原数组,为了下次再利用
    27 }
    28 
    29 void MSort(int l,int r)
    30 {
    31     if(l<r)
    32     {
    33         int mid=(l+r)/2;
    34         MSort(l,mid);
    35         MSort(mid+1,r);
    36         MArray(l,mid,r);
    37     }
    38 }
    39 
    40 int main()
    41 {
    42     ios::sync_with_stdio(false); cin.tie(0);
    43 
    44     cin>>n;
    45     for(int i=1;i<=n;i++) cin>>a[i];
    46 
    47     MSort(1,n);
    48 
    49     for(int i=1;i<=n-1;i++) cout<<a[i]<<' ';
    50     cout<<a[n]<<endl;
    51 
    52     return 0;
    53 }

    快速排序(冒泡改进而来,稳定排序)

    sort无疑是一个很浪费的算法,sort其实就是快速排序,而快速排序其实就是二分的思想。

    因为所谓的快排效率高,是针对随机的数列的。

    而一轮比赛下来,有一半人的相对顺序已经确定了,所以快排就没有了优势。(因此,归并排序优势就体现出来了,稳定排序)

      1 //普通快排基础书本写法(虽说基准数选第一个好写,但最坏情况n^2易出现,有的题专门卡这个,所以后面一般优化选中值)
      2 #include <iostream>
      3 #include <string>
      4 #include <algorithm>
      5 #include <cstdio>
      6 #include <cstring>
      7 using namespace std;
      8 const int maxn=1e5+5;
      9 int a[maxn];
     10 int n;
     11 
     12 int Partition(int l,int r)
     13 {
     14     int i=l,j=r;
     15     int temp=a[l];//为了比较,和最后相等时归位
     16     while(i<j)
     17     {
     18         while(i<j && a[j]>=temp) j--;//必须先进行j指针比较!必须>=,当>时4,2,4,5,1死循环
     19         a[i]=a[j];//即使相等也无所谓,和自己交换不影响
     20 
     21         while(i<j && a[i]<=temp) i++;
     22         a[j]=a[i];
     23     }
     24     a[i]=temp;//i,j相等时中轴归位
     25 
     26     return i;
     27 }
     28 
     29 void QSort(int l,int r)
     30 {
     31     if(l<r)
     32     {
     33         int pivotloc=Partition(l,r);//获取中轴位置,并调整顺序将序列一分为二
     34         QSort(l,pivotloc-1);//递归左子序列再一分为二
     35         QSort(pivotloc+1,r);//递归右子序列再一分为二
     36     }
     37 }
     38 
     39 int main()
     40 {
     41     ios::sync_with_stdio(false); cin.tie(0);
     42 
     43     cin>>n;
     44     for(int i=1;i<=n;i++) cin>>a[i];
     45 
     46     QSort(1,n);
     47 
     48     for(int i=1;i<n;i++) cout<<a[i]<<' ';
     49     cout<<a[n]<<endl;
     50 
     51     return 0;
     52 }
     53 //普通快排另一种写法(两个都找到了再交换一样效果)
     54 #include <iostream>
     55 #include <string>
     56 #include <algorithm>
     57 #include <cstdio>
     58 #include <cstring>
     59 using namespace std;
     60 const int maxn=1e5+5;
     61 int a[maxn];
     62 int n;
     63 
     64 int Partition(int l,int r)
     65 {
     66     int i=l,j=r;
     67     int temp=a[l];//为了比较,和最后相等时归位
     68     while(i<j)
     69     {
     70         while(i<j && a[j]>=temp) j--;//必须先进行j指针比较!
     71 
     72         while(i<j && a[i]<=temp) i++;
     73 
     74         swap(a[j],a[i]);
     75     }
     76     a[l]=a[i];//i,j相等时不符合结束回到第一个元素
     77     a[i]=temp;//中轴归位
     78 
     79     return i;
     80 }
     81 
     82 void QSort(int l,int r)
     83 {
     84     if(l<r)
     85     {
     86         int pivotloc=Partition(l,r);//获取中轴位置,并调整顺序将序列一分为二
     87         QSort(l,pivotloc-1);//递归左子序列再一分为二
     88         QSort(pivotloc+1,r);//递归右子序列再一分为二
     89     }
     90 }
     91 
     92 int main()
     93 {
     94     ios::sync_with_stdio(false); cin.tie(0);
     95 
     96     cin>>n;
     97     for(int i=1;i<=n;i++) cin>>a[i];
     98 
     99     QSort(1,n);
    100 
    101     for(int i=1;i<n;i++) cout<<a[i]<<' ';
    102     cout<<a[n]<<endl;
    103 
    104     return 0;
    105 }
    106 //优化1:普通快排+三数去中法
    107 #include <iostream>
    108 #include <string>
    109 #include <algorithm>
    110 #include <cstdio>
    111 #include <cstring>
    112 using namespace std;
    113 const int maxn=1e5+5;
    114 int a[maxn];
    115 int n;
    116 
    117 int Partition(int l,int r)
    118 {
    119     int i=l,j=r;
    120 
    121     int m=(l+r)/2;
    122     if(a[l]>a[r]) swap(a[l],a[r]);//三数取中法
    123     if(a[m]>a[r]) swap(a[m],a[r]);
    124     if(a[m]>a[l]) swap(a[m],a[l]);
    125 
    126     int temp=a[l];//为了比较,和最后相等时归位
    127     while(i<j)
    128     {
    129         while(i<j && a[j]>=temp) j--;//必须先进行j指针比较!
    130         a[i]=a[j]
    131         while(i<j && a[i]<=temp) i++;
    132         a[j]=a[i];
    133     }
    134     a[i]=temp;//i,j相等时中轴归位
    135 
    136     return i;
    137 }
    138 
    139 void QSort(int l,int r)
    140 {
    141     if(l<r)
    142     {
    143         int pivotloc=Partition(l,r);//获取中轴位置,并调整顺序将序列一分为二
    144         QSort(l,pivotloc-1);//递归左子序列再一分为二
    145         QSort(pivotloc+1,r);//递归右子序列再一分为二
    146     }
    147 }
    148 
    149 int main()
    150 {
    151     ios::sync_with_stdio(false); cin.tie(0);
    152 
    153     cin>>n;
    154     for(int i=1;i<=n;i++) cin>>a[i];
    155 
    156     QSort(1,n);
    157 
    158     for(int i=1;i<n;i++) cout<<a[i]<<' ';
    159     cout<<a[n]<<endl;
    160 
    161     return 0;
    162 }
    163 //优化2:普通快排+三数去中法+三向切分法(针对大量重复元素!)
    164 #include <iostream>
    165 #include <string>
    166 #include <algorithm>
    167 #include <cstdio>
    168 #include <cstring>
    169 using namespace std;
    170 const int maxn=1e5+5;
    171 int a[maxn];
    172 int n;
    173 
    174 int Partition(int l,int r)
    175 {
    176     int i=l,j=r;
    177 
    178     int m=(l+r)/2;
    179     if(a[l]>a[r]) swap(a[l],a[r]);//三数取中法
    180     if(a[m]>a[r]) swap(a[m],a[r]);
    181     if(a[m]>a[l]) swap(a[m],a[l]);
    182 
    183     int temp=a[l];//为了比较,和最后相等时归位
    184     while(i<j)
    185     {                               //为什么不是>=
    186         while(i<j && a[j]>temp) j--;//优化关键,>和i++
    187         if(i<j)
    188         {
    189             a[i]=a[j];
    190             i++;//为什么要i++?
    191         }
    192         while(i<j && a[i]<temp) i++;
    193         if(i<j)
    194         {
    195             a[j]=a[i];
    196             j--;
    197         }
    198     }
    199     a[i]=temp;//i,j相等时中轴归位
    200 
    201     return i;
    202 }
    203 
    204 void QSort(int l,int r)
    205 {
    206     if(l<r)
    207     {
    208         int pivotloc=Partition(l,r);//获取中轴位置,并调整顺序将序列一分为二
    209         QSort(l,pivotloc-1);//递归左子序列再一分为二
    210         QSort(pivotloc+1,r);//递归右子序列再一分为二
    211     }
    212 }
    213 
    214 int main()
    215 {
    216     ios::sync_with_stdio(false); cin.tie(0);
    217 
    218     cin>>n;
    219     for(int i=1;i<=n;i++) cin>>a[i];
    220 
    221     QSort(1,n);
    222 
    223     for(int i=1;i<n;i++) cout<<a[i]<<' ';
    224     cout<<a[n]<<endl;
    225 
    226     return 0;
    227 }

    插入排序(基础排序中用最多,当数较少!或基本有序!时,性能是最好的!)

     1 #include <iostream>
     2 #include <string>
     3 #include <algorithm>
     4 #include <iomanip>
     5 #include <cstdio>
     6 #include <cstring>
     7 using namespace std;
     8 const int maxn=1e6+5;
     9 int a[maxn];
    10 int n;
    11 
    12 void ISort()
    13 {
    14     for(int i=2;i<=n;i++)
    15     {
    16         if(a[i]<a[i-1])//>=有序,直接跳过(减少了比较次数,但交换移动次数没变)
    17         {
    18             int temp=a[i];
    19             a[i]=a[i-1];//直接先移动一个
    20 
    21             int j;
    22             for(j=i-2;a[j]>temp&&j>=1;j--) a[j+1]=a[j];//从后往前找位置(找的同时顺便移了位置),<时找到停下来插入(j>=1防止负数时死循环)
    23 
    24             a[j+1]=temp;
    25         }
    26     }
    27 }
    28 
    29 int main()
    30 {
    31     ios::sync_with_stdio(false); cin.tie(0);
    32 
    33     cin>>n;
    34     for(int i=1;i<=n;i++) cin>>a[i];
    35 
    36     ISort();
    37 
    38     for(int i=1;i<=n-1;i++) cout<<a[i]<<' ';
    39     cout<<a[n]<<endl;
    40 
    41     return 0;
    42 }

    冒泡排序(交换这种思想用得挺多)

     1 #include <iostream>
     2 #include <string>
     3 #include <algorithm>
     4 #include <iomanip>
     5 #include <cstdio>
     6 #include <cstring>
     7 using namespace std;
     8 const int maxn=1e6+5;
     9 int a[maxn];
    10 int n;
    11 
    12 void Swap(int &a,int &b)
    13 {
    14     int t=a;
    15     a=b;
    16     b=t;
    17 }
    18 
    19 void BSort()
    20 {
    21     for(int i=1;i<=n-1;i++)//每轮比较之后浮出一个最大的放到后面(只要有,比较后就交换移动)
    22     {
    23         for(int j=1;j<=n-i;j++)
    24         {
    25             if(a[j]>a[j+1])
    26             {
    27                 Swap(a[j],a[j+1]);
    28             }
    29         }
    30     }
    31 }
    32 
    33 int main()
    34 {
    35     ios::sync_with_stdio(false); cin.tie(0);
    36 
    37     cin>>n;
    38     for(int i=1;i<=n;i++) cin>>a[i];
    39 
    40     BSort();
    41 
    42     for(int i=1;i<=n-1;i++) cout<<a[i]<<' ';
    43     cout<<a[n]<<endl;
    44 
    45     return 0;
    46 }

     选择排序(比较后,有条件选择进行)

     1 #include <iostream>
     2 #include <string>
     3 #include <algorithm>
     4 #include <iomanip>
     5 #include <cstdio>
     6 #include <cstring>
     7 using namespace std;
     8 const int maxn=1e6+5;
     9 int a[maxn];
    10 int n;
    11 
    12 void Swap(int &a,int &b)
    13 {
    14     int t=a;
    15     a=b;
    16     b=t;
    17 }
    18 
    19 void SSort()
    20 {
    21     for(int i=1;i<=n-1;i++)//每轮选出一个最小的放到前面(相比冒泡减少了交换移动次数,但比较次数没变)
    22     {
    23         int k=i;
    24         for(int j=i+1;j<=n;j++) if(a[j]<a[k]) k=j;//循环之后,j是最小值下标
    25 
    26         Swap(a[i],a[k]);
    27     }
    28 }
    29 
    30 int main()
    31 {
    32     ios::sync_with_stdio(false); cin.tie(0);
    33 
    34     cin>>n;
    35     for(int i=1;i<=n;i++) cin>>a[i];
    36 
    37     SSort();
    38 
    39     for(int i=1;i<=n-1;i++) cout<<a[i]<<' ';
    40     cout<<a[n]<<endl;
    41 
    42     return 0;
    43 }
  • 相关阅读:
    【oracle】查看表空间对应文件所在位置
    【oracle】查看表空间信息
    【java异常】java.lang.Integer cannot be cast to java.lang.String
    【oracle】DATE输出是什么东西
    数字万用表的精度和分辨率,ADC的位数
    二阶系统
    Verilog中实现电平检测
    模拟信号和数字信号,直流信号和交流信号
    噪声:强度,方差信噪比(待完善)
    Simulink模块之Band-Limited White Noise
  • 原文地址:https://www.cnblogs.com/redblackk/p/9693299.html
Copyright © 2011-2022 走看看