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 }
时间: 2024-11-05 16:59:04

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

java几种常见的排序算法总结

[java] view plain copy /*************几种常见的排序算法总结***************************/ package paixu; public class PaiXu { final int MAX=20; int num[]=new int[MAX]; { System.out.print("生成的随机数组是:"); for(int i=0;i<20;i++){ num[i]=(int)(Math.random()*100)

归并排序是一种有效的排序算法

gamefrye 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 将已有序的子序列合并,得到完全有序的序列:即先使每个子序列有序,再使子序列段间有序.若将两个有序表合并成一个有序表,称为二路归并. 归并排序的基本思想 将待排序序列R[0...n-1]看成是n个长度为1的有序序列,将相邻的有序表成对归并,得到n/2个长度为2的有序表:将这些有序序列再次归并,得到n/4个长度为4的有序序列:如此反复进行下去,最后得到一

7 种常用的排序算法直观感受

1. 快速排序 介绍: 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来,且在大部分真实世界的数据,可以决定设计的选择,减少所需时间的二次方项之可能性. 步骤: 从数列中挑出一个元素,称为 "基准"(pivot), 重新排序数列,所有元

视觉直观感受 7 种常用的排序算法

1. 快速排序 介绍: 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来,且在大部分真实世界的数据,可以决定设计的选择,减少所需时间的二次方项之可能性. 步骤: 从数列中挑出一个元素,称为 "基准"(pivot), 重新排序数列,所有元

编程算法 - 高速排序算法 代码(C)

高速排序算法 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 经典的高速排序算法, 作为一个编程者, 不论什么时候都要完整的手写. 代码: /* * main.cpp * * Created on: 2014.6.12 * Author: Spike */ /*eclipse cdt, gcc 4.8.1*/ #include <stdio.h> #include <stdlib.h> int RandomInRange(int mi

java桶式排序算法代码下载

原文:java桶式排序算法代码下载 代码下载地址:http://www.zuidaima.com/share/1550463272176640.htm 桶式排序: * 桶式排序不再是基于比较的了,它和基数排序同属于分配类的排序, * 这类排序的特点是事先要知道待排 序列的一些特征. * 桶式排序事先要知道待排 序列在一个范围内,而且这个范围应该不是很大的. * 比如知道待排序列在[0,M)内,那么可以分配M个桶,第I个桶记录I的出现情况, * 最后根据每个桶收到的位置信息把数据输出成有序的形式.

7 种常用的排序算法-视觉直观感受

7 种常用的排序算法-可视化 1. 快速排序 介绍: 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来,且在大部分真实世界的数据,可以决定设计的选择,减少所需时间的二次方项之可能性. 步骤: 从数列中挑出一个元素,称为 “基准”(pivot),

几种常用的排序算法总结

主要针对于插入排序,交换(冒泡和快速),选择,堆排序,归并这几种排序的基本原理和时间复杂度,及空间复杂度的一个总结. 一.插入排序 基本执行过程:3  5  2  7  9  8 1.从小到大:从第二个数开始,每次比较都与前边的几个数进行比较 但是从大到小,要先与前边排好序的几个数中的最大的开始进行比较即倒序比较,依次往前推. 如:5 先与3进行比较,比3大,所以直接排在3的后边为:3 5: 2要先与5进行比较,比5小,再与3比较,比3小,所以排序后为 2 3 5: 7要先与5比,比5大,所以直

几种常见的排序算法

1.插入类排序 在一个已经有序的序列中,插入一个新的记录.有直接插入排序.折半插入排序.希尔排序. 插入类排序 直接插入排序 1 void InsertSort(int R[], int n) 2 { 3 int i, j; 4 int temp; 5 for (i = 1; i < n; ++i) 6 { 7 temp = R[i]; 8 j = i - 1; 9 while (j >= 0 && temp < R[j]) 10 { 11 R[j+1] = R[j];