十大排序算法(原理及代码实现细节)

Posted mch5201314

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了十大排序算法(原理及代码实现细节)相关的知识,希望对你有一定的参考价值。

技术图片

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

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

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

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

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

按上面的顺序来吧

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

冒泡排序动图演示

技术图片

冒泡排序代码实现

技术图片
 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

 

最后各排序算法对比

技术图片

 

以上是关于十大排序算法(原理及代码实现细节)的主要内容,如果未能解决你的问题,请参考以下文章

十大排序算法思想与 Python 实现 #私藏项目实操分享#

C#实现——十大排序算法之选择排序

十大排序算法总结(Python3实现)

十大排序算法——冒泡排序

十大经典排序算法的算法描述和代码实现

❥十大排序算法❥爆肝两万字保姆级教程(文字解析+图解+代码实现+例题)