zoukankan      html  css  js  c++  java
  • 十大排序算法(原理及代码实现细节)

    本文参考一些书籍啊哈算法,数据结构与算法(清华大学),以及一些网上的博客

    然后动图也是从网上偷来的(^_^),代码实现我尽量用大家容易懂的方式实现

    数组居多,然后,桶排序(是别人代码,不过写的不完全正确后面会更新),都是学习嘛

    有误的地方,还望各位指正,希望对你有帮助(其实很灵活的,在运用上),也不要这样就满足了

    多多地运用,会使理解更深的。

    按上面的顺序来吧

    原理在代码里直接上动图吧

    冒泡排序动图演示

    冒泡排序代码实现

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<string.h>
     4 using namespace std;
     5 const int N = 1e5 + 10;
     6 int a[N];
     7 //1.比较相邻的元素。如果第一个比第二个大,就交换它们两个;
     8 //当然如果你是降序那就,第一个比第二个小,就交换它们两个;
     9 //2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,
    10 //这样在最后的元素应该会是最大的数;
    11 //3.针对所有的元素重复以上的步骤,除了最后一个;
    12 //重复步骤1~3,直到排序完成。
    13 void Bubble_sort(int* arr, int len)
    14 {
    15     for(int i = 1;i < len;i++)
    16         for(int j = 1;j <= len - i;j++)
    17             if (arr[j] > arr[j + 1])//升序
    18             {
    19                 int tem = arr[j];
    20                 arr[j] = arr[j + 1];
    21                 arr[j + 1] = tem;
    22             }
    23 }
    24 
    25 int main()
    26 {
    27     int n;
    28     while (cin >> n)
    29     {
    30         for (int i = 1; i <= n; i++)
    31             cin >> a[i];
    32         Bubble_sort(a, n);
    33         cout << "After Bubble_sort:
    ";
    34         for (int i = 1; i <= n; i++)
    35             cout << a[i] << " 
    "[i == n];
    36     }
    37     return 0;
    38 }
    View Code

    快速排序动图演示

    快速排序代码实现

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 const int N = 1e5 + 10;
     5 int a[N];
     6 
     7 //它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,
     8 //其中一部分的所有数据都比另外一部分的所有数据都要小,
     9 //然后再按此方法对这两部分数据分别进行快速排序
    10 //整个排序过程可以递归进行,以此达到整个数据变成有序序列
    11 
    12 void quick_sort(int L, int R, int* arr)
    13 {
    14     if (L >= R) return;
    15     int MostL = arr[L];
    16     int i = L, j = R;
    17     while (i != j)
    18     {
    19         //先从最右边找出小于第一个元素的位置
    20         while (arr[j] >= MostL && i < j)
    21             --j;
    22 
    23         //然后从最左侧找出大于第一个元素的位置
    24         while (arr[i] <= MostL && i < j)
    25             ++i;
    26 
    27         //如果两个哨兵没有相遇交换二者
    28         if (i < j)
    29         {
    30             int tem = arr[i];
    31             arr[i] = arr[j];
    32             arr[j] = tem;
    33         }
    34     }
    35 
    36     //将第一个元素放在它应该在的位置
    37     arr[L] = arr[i];
    38     arr[i] = MostL;
    39 
    40     //对于当前哨兵位置的两侧还未有序,递归调用即可
    41     quick_sort(L, i - 1, arr);
    42     quick_sort(i + 1, R, arr);
    43 }
    44 
    45 int main()
    46 {
    47     int n;
    48     while (cin >> n)
    49     {
    50         for (int i = 1; i <= n; i++)
    51             cin >> a[i];
    52 
    53         quick_sort(1, n, a);
    54         puts("After quick_sort:");
    55         for (int i = 1; i <= n; i++)
    56             cout << a[i] << " 
    "[i == n];
    57     }
    58     return 0;
    59 }
    View Code

    插入排序动图演示

    插入排序代码实现

     1 //插入排序的工作原理是通过构建有序序列,对于未排序数据,
     2 //在已排序序列中从后向前扫描,找到相应位置并插入。
     3 //具体算法描述如下:
     4 
     5 //1.从第一个元素开始,该元素可以认为已经被排序;
     6 //2.取出下一个元素,在已经排序的元素序列中从后向前扫描;
     7 //3.如果该元素(已排序)大于新元素,将该元素移到下一位置;
     8 //4.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
     9 //5.将新元素插入到该位置后;
    10 //6.重复步骤2~5
    11 //其实有点像我们玩扑克理牌的时候,不过我们可以观察,就不会这么死的步骤了
    12 #include<bits/stdc++.h>
    13 using namespace std;
    14 const int N = 1e4 + 10;
    15 
    16 int a[N];
    17 
    18 void Insertion_sort(int *arr,int len)
    19 {
    20   for(int i = 1;i < len;i++)
    21   {
    22      int Invalue = arr[i+1];//要插入的值
    23       int curIndex = i;//当前位置
    24       //找到插入的位置
    25       while(curIndex >= 1 && arr[curIndex] > Invalue)
    26       {
    27           arr[curIndex + 1] = arr[curIndex];
    28           --curIndex;
    29       }
    30       //在后面插入值
    31       arr[curIndex + 1] = Invalue;
    32   }
    33 }
    34 
    35 int main()
    36 {
    37     int n;
    38     while(cin >> n)
    39     {
    40         for(int i = 1;i <= n;i++)
    41             cin >> a[i];
    42         Insertion_sort(a,n);
    43         puts("After Insertion_sort:");
    44         for(int i = 1;i <= n;i++)
    45             cout << a[i] << " 
    "[i == n];
    46     }
    47     return 0;
    48 }
    View Code

    希尔排序动图演示

    希尔排序代码实现

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N = 1e4 + 10;
     4 int a[N];
     5 
     6 void shell_sort(int *arr,int len)
     7 {
     8     if(arr == NULL || len <= 0)
     9     return;
    10     int cnt = 1;
    11     for(int gap = len >> 1;gap > 0;gap >>= 1)
    12     {
    13         if(gap == 2) gap++;
    14         cout << "gap = " << gap << endl;
    15         for(int i = gap + 1;i <= len;i++)
    16         {
    17             cout << "i = " << i << endl;
    18             int tem = arr[i];
    19             int j = i - gap;
    20             while(arr[j] > tem && j >= 1)
    21             {
    22                 cout << "j = " << j << endl;
    23                 arr[j+gap] = arr[j];
    24                 j -= gap;
    25             }
    26             arr[j+gap] = tem;
    27         }
    28 //        cout << cnt++ << ":
    ";
    29 //        for(int i = 1;i <= len;i++)
    30 //            cout << arr[i] << " 
    "[i == len];
    31     }
    32 }
    33 //10
    34 //49 38 65 97 76 13 27 49 55 04
    35 int main()
    36 {
    37     int n;
    38     while(cin >> n)
    39     {
    40         for(int i = 1;i <= n;i++)
    41         cin >> a[i];
    42         shell_sort(a,n);
    43 
    44         puts("After shell_sort:");
    45         for(int i = 1;i <= n;i++)
    46         cout << a[i] << " 
    "[i == n];
    47     }
    48     return 0;
    49 }
    View Code

    选择排序动态图演示

    选择排序代码实现

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N = 1e5 + 10;
     4 int a[N];
     5 //选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理
     6 //首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,
     7 //然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
     8 //以此类推,直到所有元素均排序完毕。
     9 void Selection_sort(int *arr,int len)
    10 {
    11     for(int i = 1;i < len;i++)
    12     {
    13         int Minindex = i;
    14         for(int j = i + 1;j <= len;j++)
    15         if(arr[j] < arr[Minindex])
    16         {
    17             Minindex = j;
    18         }
    19         int tem = arr[Minindex];
    20         arr[Minindex] = arr[i];
    21         arr[i] = tem;
    22     }
    23 }
    24 
    25 int main()
    26 {
    27     int n;
    28     while(cin >> n)
    29     {
    30         for(int i = 1;i <= n;i++)
    31             cin >> a[i];
    32         Selection_sort(a,n);
    33         puts("After Selection_sort:");
    34         for(int i = 1;i <= n;i++)
    35             cout << a[i] << " 
    "[i == n];
    36     }
    37     return 0;
    38 }
    View Code

    堆排序动图演示

    堆排序代码实现

      1 //堆排序,是指利用堆这种数据结构所设计的一种排序算法。
      2 //堆是一个近似完全二叉树的结构,并同时满足堆积的性质:
      3 //即子结点的键值或索引总是小于(或者大于)它的父节点。
      4 //
      5 //步骤:
      6 //在最小堆的数据结构中,堆中的最小值总是位于根节点
      7 //在优先队列中使用堆的话堆中的最小值位于根节点 堆中定义以下几种操作:
      8 //最小堆调整:将堆的末端子节点作调整,使得子节点永远大于父节点
      9 //创建最小堆:将堆中的所有数据重新排序
     10 //
     11 //堆排序:移除位在第一个数据的根节点,并做最大堆调整的递归运算
     12 //其实说白了就是一种有某种性质的数据结构
     13 //然后你做什么改动,都必须通过调整来维护该性质
     14 
     15 #include<bits/stdc++.h>
     16 using namespace std;
     17 const int N = 1e4 + 10;
     18 int h[N];
     19 int n;
     20 
     21 void Swap(int x,int y)
     22 {
     23     int tem = h[x];
     24     h[x] = h[y];
     25     h[y] = tem;
     26 }
     27 
     28 //传入一个向下调整的结点编号i
     29 void shiftdown(int i)
     30 {
     31     int t,flag = 0;//t用于记录较大值结点编号,flag用于标记是否需要下调整
     32     //当i有儿子,且需要调整是进行下面的操作
     33     while(i*2 <= n && !flag )
     34     {
     35         if(h[i] < h[i*2])//和左儿子比较
     36         t = 2*i;
     37         else t = i;
     38         //如果有右儿子再比较
     39         if(i*2 + 1 <= n)
     40         {
     41             if(h[t] < h[i*2 + 1])
     42                 t = 2*i + 1;
     43         }
     44 
     45         if(i != t)
     46         {
     47             Swap(t,i);
     48             i = t;
     49         }
     50         else flag = 1;
     51     }
     52 }
     53 
     54 //传入需要向上调整的结点i
     55 //void shiftup(int i)
     56 //{
     57 //    int flag = 0;
     58 //    if(i == 1) return;
     59 //    while(i != 1 && flag == 0)
     60 //    {
     61 //        if(h[i] < h[i/2])
     62 //            Swap(i,i/2);
     63 //        else flag = 1;
     64 //        i = i/2;//更新结点
     65 //    }
     66 //}
     67 
     68 //建立最大堆,之后最大元素是h[1]
     69 void creatHeap()
     70 {
     71     //完全二叉树有n/2个非叶结点
     72     for(int i = n/2;i >= 1;i--)
     73         shiftdown(i);
     74 }
     75 
     76 //int deleteMin()
     77 //{
     78 //    int t = h[1];
     79 //    h[1] = h[n];
     80 //    n--;
     81 //    shiftdown(1);
     82 //    return t;
     83 //}
     84 /*
     85 从小到大排序的时候不建立最小堆而建立最大堆。最大堆建立好后,
     86 最大的元素在h[ 1]。因为我们的需求是从小到大排序,
     87 希望最大的放在最后。因此我们将h[1]和h[n]交换,
     88 此时h[ n]就是数组中的最大的元素。请注意,交换后还需将h[1]向下调整以保持堆的特性。
     89 OK现在最大的元素已经归位,需要将堆的大小减1即n--,然后再将h[ 1]和h[ n]交换
     90 并将h[ 1]向下调整。如此反复,直到堆的大小变成1为止。此时数组h中的数就已经是排序好的了
     91 */
     92 void heap_sort()
     93 {
     94     while(n > 1)
     95     {
     96         Swap(1,n);
     97         n--;
     98         shiftdown(1);
     99     }
    100 }
    101 int main()
    102 {
    103     int i,num;
    104 
    105     while(cin >> num)
    106     {
    107          for(int i = 1;i <= num;i++)
    108         cin >> h[i];
    109     n = num;
    110     creatHeap();
    111     heap_sort();
    112 
    113     for(int i = 1;i <= num;i++)
    114         cout << h[i] << " 
    "[i == num];
    115     }
    116     return 0;
    117 }
    View Code

    归并排序动图演示(二路归并)

    归并排序代码实现

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N = 1e4 + 10;
     4 //该算法的主要思想是对于两个已经有序的数组进行合并是简单的
     5 //只需要对两个数组元素大小比较即可
     6 //那么刚开始只需二分数组,分出来的两个小数组又递归地
     7 //进行排序,然后有序的两个小数组就可以合并为一个大数组
     8 //分治+二分
     9 
    10 int a[N],t[N];
    11 
    12 void Merge_sort(int *arr,int *T,int l,int r)
    13 {
    14     //如果只有一个元素就不需要进行二分了
    15     if(r - l >= 1)
    16     {
    17         int m = l + (r - l)/2;
    18 
    19         //二分递归
    20         Merge_sort(arr,T,l,m);
    21         Merge_sort(arr,T,m+1,r);
    22 
    23         int i = l,j = m + 1;
    24         int nst = l;
    25 
    26         //合并两个有序的小数组
    27         while(i <= m || j <= r)
    28             if(j > r || (i <= m && arr[i] < arr[j]))
    29                 T[nst++] = arr[i++];
    30             else T[nst++] = arr[j++];
    31 
    32         for(nst = l;nst <= r;nst++)
    33             arr[nst] = T[nst];
    34     }
    35 }
    36 
    37 int main(){
    38 
    39     int n;
    40     while(cin >> n)
    41     {
    42         for(int i = 1;i <= n;i++)
    43             cin >> a[i];
    44         Merge_sort(a,t,1,n);
    45         puts("After Merge_sort:");
    46         for(int i = 1;i <= n;i++)
    47             cout << a[i] << " 
    "[i == n];
    48     }
    49     return 0;
    50 }
    View Code

    计数排序动图演示

    计数排序代码实现

     1 #include<iostream>
     2 #include<string.h>
     3 #include<cstdio>
     4 using namespace std;
     5 
     6 const int N = 1e5 + 10;
     7 int a[N],b[N];
     8 
     9 //这个算法的局限性,最大最小值之差太大就不行了,因为数组不可能开的很大
    10 void Count_sort(int n, int* A,int *B,int l,int r)
    11 {
    12     int d = (r - l);
    13     for (int i = 0; i <= d; i++)
    14         b[i] = 0;
    15 
    16     for (int i = 1; i <= n; i++)
    17         b[a[i] - l]++;
    18 }
    19 
    20 int main()
    21 {
    22     int n;
    23     while (cin >> n)
    24     {
    25         int r = -1e6,l = 1e6;
    26         for (int i = 1; i <= n; i++)
    27         {
    28             cin >> a[i];
    29             if (a[i] > r)
    30                 r = a[i];
    31             if(a[i] < l)
    32                 l = a[i];
    33         }
    34         int d = r - l;
    35         Count_sort(n, a, b, l, r);
    36 
    37         puts("After Count_sort:");
    38         for (int i = 0; i <= d; i++)
    39             for (int j = 1; j <= b[i]; j++)
    40                 cout << i + l << " ";
    41         puts("");
    42     }
    43     return 0;
    44 }
    View Code

    桶排序

    桶排序代码实现

     1 //算法描述:
     2 //首先它是建立在计数排序的基础上
     3 //你需要知道数列里的最大最小值
     4 //然后自己定义桶的个数(有些人直接分为10个桶),然后每个桶对应一个区间
     5 //把每个数放到对应的区间
     6 //每个桶内部可以用其他排序算法来排,
     7 //每个桶排序好之后,由于桶之间保存的数字大小区间不一样
     8 //最后合并所有桶就得到有序序列了
     9 //这份代码是别人写的,我本来想用一个二位数组写的,
    10 //不过用链表写也不错,我是理解了他的了,还加了一些注释
    11 //而且这个写法没有离散化,导致输入的数据不可以是负数
    12 //而且桶内的排序相当于插入排序是n^2的复杂度,是不对的,总的复杂度
    13 //居然是n^2,我表示这个不是真的桶排序
    14 #include<bits/stdc++.h>
    15 using namespace std;
    16 const int N = 1e4 + 10;
    17 int a[N];
    18 
    19 typedef struct node {
    20     int key;
    21     struct node* next;
    22 }KeyNode;
    23 
    24 void bucket_sort(int keys[], int size, int bucket_size)
    25 {
    26     KeyNode** bucket_table = (KeyNode**)malloc(bucket_size * sizeof(KeyNode*));
    27 
    28     for (int i = 0; i < bucket_size; i++) {    //初始化每个桶
    29         bucket_table[i] = (KeyNode*)malloc(sizeof(KeyNode));
    30         bucket_table[i]->key = 0;
    31         bucket_table[i]->next = NULL;
    32     }
    33 
    34     for (int i = 0; i < size; i++) {
    35         KeyNode* node = (KeyNode*)malloc(sizeof(KeyNode));
    36         node->key = keys[i];
    37         node->next = NULL;
    38 
    39         int index = keys[i] / 10;//给数据分类的方法(关系到排序速度,很重要)
    40         KeyNode* p = bucket_table[index];
    41         if (p->key == 0) {
    42             p->next = node;
    43             p->key++;
    44         }
    45         else {
    46             while (p->next != NULL && p->next->key <= node->key) {
    47             //新来的就找到自己的位置
    48             //这里选择类插入排序的方式,其实是不对的,因为这样的方式相当与每个桶内又是
    49             //n^2复杂度
    50                 p = p->next;
    51             }
    52             node->next = p->next;
    53             p->next = node;
    54             (bucket_table[index]->key)++;//这个桶当前数据量加一
    55         }
    56     }
    57 
    58     KeyNode* k = NULL;
    59     //遍历每个桶
    60     for (int i = 0; i < bucket_size; i++) {
    61         for (k = bucket_table[i]->next; k != NULL; k = k->next) {
    62             printf("%d ", k->key);
    63         }
    64     }
    65 }
    66 
    67 int main()
    68 {
    69     int n;
    70     while(cin >> n)
    71     {
    72         for(int i = 0;i < n;i++)
    73         cin >> a[i];
    74         puts("After bucket_sort:");
    75         bucket_sort(a, n, 10);
    76     }
    77     return 0;
    78 }
    View Code

    基数排序动态图演示

    基数排序代码实现

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int a[100];
     4 int n, ma;
     5 void work(int cur) {
     6     int b[10] = { 0 };
     7     int c[100];
     8     for (int i = 0; i < n; i++)
     9         b[(a[i] / cur) % 10]++;
    10 
    11     for (int i = 1; i < 10; i++)
    12         b[i] += b[i - 1];//前缀和,b[i]表示当前位小于等于i的数字有多少个
    13 
    14 //   下面这个地方尤为关键为啥从n - 1开始,而不是从0开始
    15 //   因为是从最低位开始调整位置的,前面已经在低位排好了,如果从0开始
    16 //   如果当前位两个数字为0,那么他们的相对位置应该不变
    17 //   从0开始就反了,顺序错了
    18 
    19     for (int i = n - 1; i >= 0; i--)
    20     {
    21         //精髓所在
    22         c[b[(a[i] / cur) % 10] - 1] = a[i];
    23         b[(a[i] / cur) % 10]--;
    24     }
    25 
    26     //复制一份给原始数据
    27     for (int i = 0; i < n; i++)
    28         a[i] = c[i];
    29 }
    30 
    31 void radix_sort() {
    32     //1代表各位的比较,10代表十位的比较,依此类推
    33     for (int i = 1; ma / i > 0; i *= 10)
    34         work(i);
    35 }
    36 
    37 int main() {
    38 
    39     while (cin >> n) {
    40         ma = 0;
    41         for (int i = 0; i < n; i++) {
    42             cin >> a[i];
    43             if(a[i] > ma) ma = a[i];
    44         }
    45         puts("before sort");
    46         for (int i = 0; i < n; i++)
    47             cout << a[i] << ' ';
    48         puts("");
    49         radix_sort();
    50         puts("after radix_sort");
    51         for (int i = 0; i < n; i++)
    52             cout << a[i] << ' ';
    53         puts("");
    54     }
    55     return 0;
    56 }
    View Code

    最后各排序算法对比

  • 相关阅读:
    Idea maven项目不能新建package和class的解决【转】
    Spring事务管理源码分析
    POI操作EXCEL之导出Excel(设置有效性,下拉列表引用)
    Idea之Tomcat
    idea 之git使用详细教程
    Redisson教程
    Redisson整合Spring
    IntelliJ IDEA 工具技巧
    nginx代理tomcat后,tomcat获取真实(非proxy,非别名)nginx服务端ip端口的解决方案
    Idea构建Maven项目教程
  • 原文地址:https://www.cnblogs.com/mch5201314/p/11672012.html
Copyright © 2011-2022 走看看