七种排序算法的实现和总结

最近把七种排序算法集中在一起写了一遍。

注释里有比较详细的说明。

  1 /*排序算法大集合**/
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <stdlib.h>
  5
  6 //------------------快速排序------------------//
  7 /*
  8 核心:
  9 如果你知道多少人该站你前面,多少人站你后面,你一定知道你该站哪个位置。
 10 算法:
 11 1.选取分界数,参考这个分界数,大于参考数放在右边,小于的放在左边。
 12  2.对左右两边的序列分别递归进行1处理
 13  3.将整个序列合并得到有序结果
 14  */
 15 //分区函数
 16 int Part(int Array[],int left, int right)
 17 {
 18     int temp;
 19     temp = Array[left];//选取第一个数为分界数
 20     while(left < right)
 21     {
 22         while(left < right && Array[right] > temp)
 23         {
 24             right--;
 25         }
 26         Array[left] = Array[right];
 27         while(left<right && Array[left]<=temp)
 28         {
 29             left++;
 30         }
 31         Array[right] = Array[left];
 32     }
 33     Array[left] = temp;
 34     return left;
 35 }
 36 void Quicksort(int Array[],int left, int right)
 37 {
 38     if(left < right)
 39     {
 40         int p= Part(Array, left, right);
 41         Quicksort(Array, left, p-1);
 42         Quicksort(Array, p+1, right);
 43     }
 44 }
 45 //------------------插入排序------------------//
 46 /*
 47 核心:
 48 每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中的适当位置,直到全部记录插入完成为止。
 49 算法:
 50 1.初始时,a[0]自成1个有序区,无序区为a[1..n-1]。令i=1
 51 2.将a[i]并入当前的有序区a[0…i-1]中形成a[0…i]的有序区间。
 52 3. i++并重复第二步直到i==n-1。排序完成。
 53 */
 54 void InsertSort(int a[], int n)
 55 {
 56     int i, j, temp;
 57     for(i = 1; i < n; ++i)
 58     {
 59         if(a[i] < a[i - 1])
 60         {
 61             temp = a[i];
 62             for(j = i - 1; j >= 0 && a[j] > temp; --j)
 63                 a[j + 1] = a[j];
 64             a[j + 1] = temp;
 65         }
 66     }
 67 }
 68 //------------------选择排序------------------//
 69 /*
 70 核心:
 71 选择排序将数据分为有序区和无序区从无序区选一个最小的元素直接放到有序区的最后。
 72 算法:
 73 1.初始时,数组全为无序区为a[0..n-1]。令i=0
 74 2.在无序区a[i…n-1]中选取一个最小的元素,将其与a[i]交换。交换之后a[0…i]就形成了一个有序区。
 75 3.i++并重复第二步直到i==n-1。排序完成。
 76 */
 77 void SelectionSort(int a[], int n)
 78 {
 79     int min, i, j;
 80     for(i = 0; i < n - 1; ++i)
 81     {
 82         min = i;
 83         for(j = i + 1; j < n; ++j)
 84             if(a[j] < a[min])
 85                 min = j;
 86
 87         if(min != i)
 88         {
 89             int t = a[i];
 90             a[i] = a[min];
 91             a[min] = t;
 92         }
 93     }
 94 }
 95
 96 //------------------冒泡排序------------------//
 97 /*
 98 算法:
 99 1.比较相邻的前后二个数据,如果前面数据大于后面的数据,就将二个数据交换。
100 2.这样对数组的第0个数据到N-1个数据进行一次遍历后,最大的一个数据就“沉”到数组第N-1个位置。
101 3.N=N-1,如果N不为0就重复前面二步,否则排序完成。
102 分析:
103 冒泡排序毕竟是一种效率低下的排序方法,在数据规模很小时,可以采用。数据规模比较大时,最好用其它排序方法。
104 */
105 void swap(int &a, int &b)
106 {
107     int t = a;
108     a = b;
109     b = t;
110 }
111
112 void BubbleSort(int a[], int n)
113 {
114     int i, j, flag = n;//用flag来记录a[flag]后面的有序数列,便不再比较
115     while(flag > 0)
116     {
117         j = flag;
118         flag = 0;
119         for(i = 0; i < j; ++i)
120             if(a[i] < a[i - 1])
121             {
122                 swap(a[i], a[i - 1]);
123                 flag = j;
124             }
125     }
126 }
127
128 //------------------堆排序------------------//
129 /*
130 数据结构:
131 堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:
132 任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。
133 堆分为大顶堆和小顶堆,
134 大顶堆的堆顶的关键字肯定是所有关键字中最大的,
135 小顶堆的堆顶的关键字是所有关键字中最小的。
136 算法:
137  1)将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无序区;
138  2)将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n];
139  3)由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,......Rn-1)调整为新堆,
140  然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2....Rn-2)和新的有序区(Rn-1,Rn)。
141  不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。
142 */
143 void HeapAdjust(int a[], int i, int size)//堆的构造
144 {
145     int LeftChild = i * 2;
146     int RightChild = LeftChild + 1;
147     if(i <= size / 2)
148     {
149         int max = i;
150         if(a[LeftChild] > a[max])
151             max = LeftChild;
152         if(RightChild <= size && a[RightChild] > a[max])
153             max = RightChild;
154         if(max != i)
155         {
156             swap(a[i], a[max]);
157             HeapAdjust(a, max, size);
158         }
159     }
160 }
161
162 void HeapSort(int a[], int size)
163 {
164     int i;
165     for(i = size / 2; i >= 1; --i)//堆的初始化
166         HeapAdjust(a, i, size);
167
168     for(i = size; i > 1; --i)
169     {
170         swap(a[1], a[i]);
171         HeapAdjust(a, 1, i - 1);
172     }
173 }
174
175 //------------------归并排序------------------//
176 /*
177 算法:
178     并:
179         将二个有序数列合并,只要从比较二个数列的第一个数,
180         谁小就先取谁,取了后就在对应数列中删除这个数。
181         然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。
182         将数组分成二组A,B,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。
183     归:
184         当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,
185         然后再合并相邻的二个小组就可以了。
186         这样通过先递归的分解数列,
187         再合并数列就完成了归并排序。
188 */
189 void MergeArray(int a[], int first, int mid, int last, int temp[])
190 //使a[first...mid]和a[mid+1...last]两部分归并为有序数列
191 {
192     int i = first, j = mid + 1;
193     int m = mid, n = last;
194     int k = 0;
195     while(i <= m && j <= n)
196     {
197         if(a[i] < a[j])
198             temp[k++] = a[i++];
199         else
200             temp[k++] = a[j++];
201     }
202
203     while(i <= m)
204         temp[k++] = a[i++];
205     while(j <= n)
206         temp[k++] = a[j++];
207
208     for(i = 0; i < k; ++i)
209         a[first + i] = temp[i];
210 }
211
212 void mergesort(int a[], int first, int last, int temp[])
213 {
214     if(first < last)
215     {
216         int mid = (first + last) / 2;
217         mergesort(a, first, mid, temp);
218         mergesort(a, mid + 1, last, temp);
219         MergeArray(a, first, mid, last, temp);
220     }
221 }
222
223 bool MergeSort(int a[], int n)
224 {
225     int *p = new int[n];
226     if(p == NULL)
227         return false;        //若内存分配失败则返回FALSE
228     mergesort(a, 0, n - 1, p);
229     delete []p;
230     return true;
231 }
232
233 //------------------LSD基数排序------------------//
234 /*
235 算法:
236 1、分配,先从个位开始,根据位值(0-9)分别放到0~9号桶中
237 2、收集,再将放置在0~9号桶中的数据按顺序放到数组中
238 3、重复(1)(2)过程,从个位到最高位
239 */
240 //a[]为常量表,用来取num的第pos位的数字
241 const int a[] = {1, 1, 10, 100, 1000, 10000,
242         100000, 1000000, 10000000, 100000000, 1000000000};
243
244 int GetNumInPos(int num, int pos)//取num的第pos位的数字
245 {
246     return ((num / a[pos]) % 10);
247 }
248
249 int FindMaxDigit(int array[], int size)//找到数组中最大的位数
250 {
251     int cnt = 1, x = 10;
252     for(int i = 0; i < size; ++i)
253     {
254         while(array[i] >= a[cnt + 1])
255             ++cnt;
256     }
257     return cnt;
258 }
259
260 void RadixSort(int array[], int size)
261 {
262     int *radixArrays[10]; //分配0~9的桶子空间
263     int i;
264     int KeyNum = FindMaxDigit(array, size);
265     for(i = 0; i < 10; ++i)
266     {
267         radixArrays[i] = (int *)malloc(sizeof(int) * (size + 1));
268         radixArrays[i][0] = 0;        //此处记录各组数据的个数
269     }
270
271     int pos;
272     for(pos = 1; pos <=KeyNum; ++pos)
273     {
274         for(i = 0; i < size; ++i)
275         {
276             int num = GetNumInPos(array[i], pos);
277             int index = ++radixArrays[num][0];
278             radixArrays[num][index] = array[i];
279         }
280         //收集
281         int j;
282         for(i = 0, j = 0; i < 10; ++i)
283         {
284             for(int k = 1; k <= radixArrays[i][0]; ++k)
285                 array[j++] = radixArrays[i][k];
286             radixArrays[i][0] = 0;
287         }
288     }
289     for(i = 0; i < 10; ++i)
290         free(radixArrays[i]);        //释放分配的空间
291 }
292
293 void PrintArr(int a[], int n)
294 {
295     for(int i = 0; i < n; ++i)
296         printf("%d  ", a[i]);
297     printf("\n");
298 }
299
300 int main(void)
301 {
302     int  array1[] = {12, 14, 54, 5, 6, 3, 9, 8, 47, 89}, array2[15];
303
304     memcpy(array2, array1, sizeof(array1));
305     int Left = 0, Right = 9;
306     Quicksort(array2, Left, Right);
307     printf("快速排序:\n");
308     PrintArr(array2, 10);
309
310     memcpy(array2, array1, sizeof(array1));
311     InsertSort(array2, 10);
312     printf("插入排序:\n");
313     PrintArr(array2, 10);
314
315     memcpy(array2, array1, sizeof(array1));
316     SelectionSort(array2, 10);
317     printf("选择排序:\n");
318     PrintArr(array2, 10);
319
320     memcpy(array2, array1, sizeof(array1));
321     BubbleSort(array2, 10);
322     printf("冒泡排序:\n");
323     PrintArr(array2, 10);
324
325     //堆排序是从a[1]开始排所以要对数组进行一下调整
326     int i;
327     for(i = 0; i < 10; ++i)
328         array2[i + 1] = array1[i];
329     HeapSort(array2, 10);
330     printf("堆排序:\n");
331     for(i = 0; i < 10; ++i)
332         printf("%d  ", array2[i + 1]);
333     printf("\n");
334
335     memcpy(array2, array1, sizeof(array1));
336     MergeSort(array2, 10);
337     printf("归并排序:\n");
338     PrintArr(array2, 10);
339
340     memcpy(array2, array1, sizeof(array1));
341     RadixSort(array2, 10);
342     printf("基数排序:\n");
343     PrintArr(array2, 10);
344
345     return 0;
346 }

七种排序算法的实现和总结

时间: 2024-08-06 11:53:18

七种排序算法的实现和总结的相关文章

数组的几种排序算法的实现

转自: http://blog.csdn.net/letthinking/article/details/6764996 . 数组的排序方法有很多,效率也各不相同,下面简单介绍一下几种常见的排序算法. 1.选择排序法:将要排序的数组分成两部分,一部分是从大到小已经排好序的,一部分是无序的,从无序的部分取出最小的放到已经排序的最后面.实现如下: [java] view plaincopy public int[] choiceSort(int[] arr){ for(int i = 0;i < a

Python - 几种排序算法的实现

直接插入.选择排序.冒泡排序.快速排序.……归并排序.基数排序.希尔.堆排序. 直接插入: 思想是:1.将数据序列分成两部分,前一部分是有序的,后面一部分是无序的. 2.将无序变有序,首先从第一开始,然后第一,第二比较后排序,此时这两位就是有序的了:然后从无序的队列中取出第三位和第二位比较,然后他们中矮的再和第一位比较,此时三位是有序的: 然后再取出第四位,和前面的比较……,一直到最后一位比较. def insert_sort(aList): n = len(aList) for i in ra

模板化的七种排序算法,适用于T* vector&lt;T&gt;以及list&lt;T&gt;

最近在写一些数据结构以及算法相关的代码,比如常用排序算法以及具有启发能力的智能算法.为了能够让写下的代码下次还能够被复用,直接将代码编写成类模板成员函数的方式,之所以没有将这种方式改成更方便的函数模板纯属于偷懒,更方便于测试代码的有效性,等代码写完也懒得去改了.下面开始介绍这段代码,有什么不对的地方欢迎前来指正. 一共写了七种排序,插入排序InsertSort.堆排序HeapSort.快速排序QuickSort.合并排序MergeSort,计数排序CountingSort,基数排序RadixSo

探讨排序算法的实现

排序算法是我们工作中使用最普遍的算法,常见的语言库中基本都会有排序算法的实现,比如c标准库的qsort,stl的sort函数等.本文首先介绍直接插入排序,归并排序,堆排序,快速排序和基数排序等比较排序算法,然后介绍计数排序,基数排序等具有线性时间的排序算法.本文主要讨论算法的实现方法,并不会过多介绍基本理论. 评价一个排序算法优劣适用与否,一般需要从三个方面来分析 时间复杂度.用比较操作和移动操作数的最高次项表示,由于在实际应用中最在乎的是运行时间的上限,所以一般取输入最坏情况的下的运行时间作为

Python学习(三) 八大排序算法的实现(下)

本文Python实现了插入排序.基数排序.希尔排序.冒泡排序.高速排序.直接选择排序.堆排序.归并排序的后面四种. 上篇:Python学习(三) 八大排序算法的实现(上) 1.高速排序 描写叙述 通过一趟排序将要排序的数据切割成独立的两部分,当中一部分的全部数据都比另外一部分的全部数据都要小,然后再按此方法对这两部分数据分别进行高速排序,整个排序过程能够递归进行,以此达到整个数据变成有序序列. 1.先从数列中取出一个数作为基准数. 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全

Python 排序算法的实现

冒泡排序: 1 def bubble(l): 2 length = len(l) 3 for i in range(length): 4 for j in range(i+1, length): 5 if l[i] > l[j]: 6 l[i], l[j] = l[j], l[i] 7 print l 选择排序: 1 def select(l): 2 length = len(l) 3 for i in range(length): 4 minn = i 5 for j in range(i+1

软考笔记第六天之各排序算法的实现

对于前面的排序算法,用c#来实现 直接插入排序: 每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序.第一趟比较前两个数,然后把第二个数按大小插入到有序表中: 第二趟把第三个数据与前两个数从前向后扫描,把第三个数按大小插入到有序表中:依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程.直接插入排序属于稳定的排序,最坏时间复杂性为O(n^2),空间复杂度为O(1).直接插入排序是由两层嵌套循环组成的.外层循环标识并决定待比较的数值.内层循环为待比较数值确定其最终位

常见排序算法的实现(归并排序、快速排序、堆排序、选择排序、插入排序、希尔排序)

这篇博客主要实现一些常见的排序算法.例如: //冒泡排序 //选择排序 //简单插入排序 //折半插入排序 //希尔排序 //归并排序 //双向的快速排序 //单向的快速排序 //堆排序 对于各个算法的实现原理,这里不再多说了,代码中注释较多,结合注释应该都能理解算法的原理,读者也可自己google一下.另外,注释中有很多点,比如边界条件.应用场景等已经用 * 标记,* 越多,越应该多注意. 下面是实现: //冒泡排序 void BubbleSort(int *arr, int n) { if(

各种排序算法的实现和比较

算法的稳定性 如果待排序表中有两个元素 Ri 和 Rj,其对应的关键字keyi = keyj,注意是关键字相等,且在排序前 Ri 排在 Rj 前面,如果使用某一算法排序后,Ri 仍在 Rj 前面,则称这个算法是稳定的,否则是不稳定的. 在排序过程中,根据元素是否完全在内存中,可以将排序算法分为两类:内部排序是指在排序期间元素全部存放在内存中的排序:外部排序是指在排序期间元素无法全部同时放在内存中,必须在排序过程中根据要求不断地在内外存之间移动. 以下所有代码基于此类结构: typedef int