8种基本的排序算法代码(不断更新)
最近看了两篇不错的博文,是介绍基本的查找和排序算法的,自己也在不断整理,先把代码放网上,参考资料如下:
以上资料中,一个没有代码,另一个使用的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 }