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

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

而后动图也是从网上偷来的(^_^),代码实现我尽可能用你们容易懂的方式实现ios

数组居多,而后,桶排序(是别人代码,不过写的不彻底正确后面会更新),都是学习嘛c++

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

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

按上面的顺序来吧数组

原理在代码里直接上动图吧数据结构

冒泡排序动图演示ide

冒泡排序代码实现学习

 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:\n"; 34         for (int i = 1; i <= n; i++) 35             cout << a[i] << " \n"[i == n]; 36  } 37     return 0; 38 }
View Code

 

快速排序动图演示ui

快速排序代码实现

 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] << " \n"[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] << " \n"[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++ << ":\n"; 29 // for(int i = 1;i <= len;i++) 30 // cout << arr[i] << " \n"[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] << " \n"[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] << " \n"[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] << " \n"[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] << " \n"[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

 

最后各排序算法对比

相关文章
相关标签/搜索