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 }
原文地址:https://www.cnblogs.com/xiaomanon/p/4379071.html