8种基本的排序算法代码(不断更新)

最近看了两篇不错的博文,是介绍基本的查找和排序算法的,自己也在不断整理,先把代码放网上,参考资料如下:

Victor Zhang

SHIroh的专栏

以上资料中,一个没有代码,另一个使用的JAVA实现,我在这里使用C语言将它们实现了。

0 头文件声明

1 #include <stdio.h>

2 #include <stdlib.h>

3 typedef int Item;

4 #define key(A) (A) //返回关键字A

5 #define less(A, B) ( key(A) < key(B) )   //返回A<B的判断结果

6 #define exch(A, B) {Item t=A; A=B; B=t;} //交换A和B的值

7 //如果B<A,则交换两者的值

8 #define compexch(A, B) { if (less(B, A)) exch(A, B) }

 

1 冒泡排序

 1 /** bubble sort

 2   */

 3 void bubble_sort(Item a[], int l, int r)

 4 {

 5     int i, j;

 6     for (i = l; i < r; i++){

 7         for (j = r; j > i; j--){

 8             compexch(a[j-1], a[j]);

 9         }

10     }

11 }

12 void bubble_sort2(Item a[], int l, int r)

13 {

14     int i, j, exchanged = 0;

15     for (i = l; i < r; i++){

16         for (j = r; j > i; j--){

17             if (less(a[j], a[j-1])){

18                 exch(a[j], a[j-1]);

19                 exchanged = 1;

20             }

21         }

22         if (exchanged != 0) return;

23     }

24 }

 

2 快速排序

 1 /** quick sort

 2   */

 3 int division(Item a[], int l, int r)

 4 {

 5     int base = a[l];//以最左边的元素为基准

 6     while (l < r){

 7         //从序列右边开始向左边遍历,直到找到小于base的数

 8         while (l < r && a[r] >= base) r--;

 9         a[l] = a[r];//找到比base小的元素,将其放到最左边的位置

10 

11         //从序列左边开始向右边遍历,直到找到大于base的数

12         while (l < r && a[l] <= base) l++;

13         a[r] = a[l];//找到比base大的元素,将其放到最右边的位置

14     }

15     //最后将base放到left指向的位置

16     a[l] = base;

17     return l;//返回分割位置

18 }

19 

20 void quick_sort(Item a[], int l, int r)

21 {

22     int base;

23     if (l < r){

24         //对数组进行分割,取出下次分割的基准编号

25         base = division(a, l, r);

26         //对基准左边的元素进行排序

27         quick_sort(a, l, base - 1);

28         //对基准右边的元素进行排序

29         quick_sort(a, base + 1, r);

30     }

31 }

 

3 插入排序

 1 /** insertion sort

 2   */

 3 void insertion_sort(Item a[], int l, int r)

 4 {

 5     int i, j;

 6     for (i = l + 1; i <= r; i++){

 7         for (j = i; j > l; j--)

 8             compexch(a[j-1], a[j]);

 9     }

10 }

11 

12 void insertion_sort2(Item a[], int l, int r)

13 {

14     int i, j, temp;

15     for (i = l + 1; i <= r; i++){

16         temp = a[i];//取出第i个元素,跟之前的i-1个数比较

17         for (j = i - 1; j >= l && temp < a[j]; j--)

18             a[j+1] = a[j];//将比temp大的数后移

19         a[j+1] = temp;//将第i个元素插入正确位置

20     }

21 }

 

4 希尔排序

 1 /** shell sort

 2   */

 3 void shell_sort(Item a[], int l, int r)

 4 {

 5     int i, j, temp, gap = (r - l + 1) / 2;

 6     while (gap >= 1){

 7         for (i = l + gap; i <= r; i++){

 8             temp = a[i];

 9             //对距离为gap的元素进行直接插入排序

10             for (j = i - gap; j >= l && temp < a[j]; j = j - gap)

11                 a[j+gap] = a[j];

12             a[j+gap] = temp;

13         }

14         gap = gap / 2;//减小增量

15     }

16 }

 

5 选择排序

 1 /** selection sort

 2   */

 3 void selection_sort(Item a[], int l, int r)

 4 {

 5     int i, j, index;

 6     for (i = l; i < r; i++){

 7         index = i;

 8         for (j = i + 1; j <= r; j++){

 9             if (less(a[j], a[index])) index = j;

10         }

11         exch(a[i], a[index]);

12     }

13 }

 

6 堆排序

 1 /**

 2   * heap sort

 3   */

 4 void heap_adjust(Item a[], Item parent, int length)

 5 {

 6     Item temp = a[parent];//保存当前父节点

 7     int  child = 2 * parent + 1;//先获得左孩子

 8 

 9     while (child < length){

10         //如果有右孩子节点,并且右孩子节点的值大于左孩子节点,则选取右孩子节点

11         if (child+1 < length && a[child] < a[child+1]){

12             child++;

13         }

14         //如果父节点的值已经大于孩子节点的值,则直接结束循环

15         if (temp >= a[child]) break;

16         //把孩子节点的值赋给父节点

17         a[parent] = a[child];

18         //选取孩子节点的左孩子节点,继续向下筛选

19         parent = child;

20         child  = 2 * parent + 1;

21     }

22     a[parent] = temp;

23 }

24 

25 void heap_sort(Item a[], int l, int r)

26 {

27     int i, length = r - l + 1;

28     //循环建立初始堆

29     for (i = length/2; i >= 0; i--){

30         heap_adjust(a, i, length - 1);

31     }

32     //进行n-1次循环,完成排序

33     for (i = length - 1; i > 0; i--){

34         exch(a[0], a[i]);//最后一个元素和第一个元素交换

35         heap_adjust(a, 0, i);//筛选R[0]节点,得到n-1个节点的堆

36     }

37 }

 

7 归并排序

 1 /** merge sort

 2   */

 3 void merge_opt(Item a[], int low, int mid, int high)

 4 {

 5     int i = low;//i是第一段序列的下标

 6     int j = mid + 1;//j是第二段序列的下标

 7     int k = 0;//k是临时存放合并序列的下标

 8     Item *R2 = (Item *)malloc((high - low + 1)*sizeof(Item));//临时合并序列

 9 

10     //扫描第一段和第二段序列,直到有一个序列扫描结束

11     while (i <= mid && j <= high){

12         // 判断第一段和第二段取出的数哪个更小,将其存入合并序列,并继续向下扫描

13         if (a[i] <= a[j]){

14             R2[k] = a[i];

15             i++; k++;

16         }else {

17             R2[k] = a[j];

18             j++; k++;

19         }

20     }

21     // 若第一段序列还没扫描完,将其全部复制到合并序列

22     while (i <= mid){

23         R2[k] = a[i];

24         i++; k++;

25     }

26     // 若第二段序列还没扫描完,将其全部复制到合并序列

27     while (j <= high){

28         R2[k] = a[j];

29         j++; k++;

30     }

31     // 将合并序列复制到原始序列中

32     for (k = 0, i = low; i <= high; i++, k++){

33         a[i] = R2[k];

34     }

35     //最后释放内存

36     free(R2);

37 }

38 

39 void merge_pass(Item a[], int gap, int length)

40 {

41     int i = 0;

42     //归并gap长度的两个相邻子表

43     for (i = 0; (i + 2 * gap - 1) < length; i = i + 2 * gap){

44         merge_opt(a, i, i + gap - 1, i + 2 * gap - 1);

45     }

46     //余下两个子表,后者长度小于gap

47     if (i + gap - 1 < length){

48         merge_opt(a, i, i + gap - 1, length - 1);

49     }

50 }

51 

52 void merge_sort(Item a[], int l, int r)

53 {

54     int gap, length = r - l + 1;

55 

56     for (gap = 1; gap < length; gap = 2 * gap){

57         merge_pass(a, gap, length);

58     }

59 }

 

8 基数排序

 1 /** Radix Sort

 2   */

 3 int max_bit(int a[], int n)//辅助函数,求数据的最大位数

 4 {

 5     int digits = 1;//保存最大的位数

 6     int i, p = 10;

 7 

 8     for (i = 0; i < n; i++){

 9         while (a[i] >= p){

10             p *= 10;

11             digits++;//位数加1

12         }

13     }

14     return digits;

15 }

16 

17 void radix_sort(int a[], int l, int r)

18 {

19     int length = r - l + 1;  //排序数组长度

20     int digits = max_bit(a, length);//数据最大位数

21     int i, j, k, radix = 1;

22     int cnt[10];//计数器

23     int *tmp =  (int *)malloc(length * sizeof(int));

24     //进行digits次排序

25     for (i = 1; i <= digits; i++){

26         //每次分配前情况计数器

27         for (j = 0; j < 10; j++){

28             cnt[j] = 0;

29         }

30         //统计每个桶中的记录数

31         for (j = l; j <= r; j++){

32             k = (a[j] / radix) % 10;

33             cnt[k]++;

34         }

35         //将tmp中的位置依次分配给每个桶

36         for (j = 1; j < 10; j++){

37             cnt[j] = cnt[j-1] + cnt[j];

38         }

39         //将所有桶中记录收集到tmp中

40         for (j = length - 1; j >= 0; j--){

41             k = (a[j] / radix) % 10;

42             tmp[cnt[k] - 1] = a[j];

43             cnt[k]--;

44         }

45         //将临时数组中的内容复制到原始数组中

46         for (j = 0; j < length; j++){

47             a[j] = tmp[j];

48         }

49         radix = 10 * radix;

50     }

51     free(tmp);

52 }

 

9 测试代码

 1 int main(int argc, char *argv[])

 2 {

 3 

 4     Item a[10] = {103, 329, 33, 2308, 22222, 35, 4, 7, 6, 30};

 5     //Item a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

 6     int  i;

 7 

 8     radix_sort(a, 0, 9);

 9     for (i = 0; i < 10; i++)

10         printf("%6d", a[i]);

11 

12     return 0;

13 }

 

你可能感兴趣的:(排序算法)