C语言算法-排序
环境
PC环境:Windows10 64bit
IDE:sublime text3
注:sublime text3需要安装C/C++编译环境处理
选择排序
特点:简单、容易实现
缺点:执行速度慢
实现过程:通过遍历的方式进行比较,找出数据中最小的(或最大的)放到起始位置,然后起始位置向前加1,再从剩下的找出最小的,以此类推
C语言实现如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43#include
#include
#define key(A) (A)
#define less(A, B) (key(A) < key(B))
#define exch(A, B) {int t = A; A = B; B = t;}
#define compexch(A, B) if(less(B, A)) exch(A, B)
int array[10] = {5, 9, 0, 1, 3, 6, 8, 7, 2, 4};
void selection_sort(int a[], int count)
{
int i, j, min;
for (i = 0; i < count; i++)
{
min = i;
for (j = i+1; j < count; j++)
{
if (a[min] > a[j])
min = j;//找到最小的(数组下标)
}
if (min != i)
{
compexch(a[i], a[min]);
}
}
}
int main()
{
int i;
int count = sizeof(array)/sizeof(array[0]);
selection_sort(array, count);
for (i = 0; i < count; i++)
{
printf("%d ", array[i]);
}
return 0;
}
代码分析:
1
2
3less-比较两个关键字
exch-交换两个元素
compexch-比较两个元素,并使第一个元素始终为最小
实现效果:
冒泡排序
特点:简单、容易实现
缺点:执行速度慢
实现过程:通过遍历的方式进行比较,把数据从小到大或从大到小进行排序;假如有十个数据:Array = {3,2,5,8,2,7,0,1,4,6},首先将第一个数据Array[0]逐次跟后面数据进行比较从而得到10个数据中的最小数(或最大数),同理,Array[1]逐次跟后面数据进行比较从而得到9个数据中的最小数(或最大数);10个数据需要比较(9+8+7+6+5+4+3+2+1)次才能完成排序,如有N个数则需要比较:N*(N-1)/2,时间复杂度为0(N^2)
C语言实现如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#include
#include
#define key(A) (A)
#define less(A, B) (key(A) < key(B))
#define exch(A, B) {int t = A; A = B; B = t;}
#define compexch(A, B) if(less(B, A)) exch(A, B)
int array[10] = {5, 9, 0, 1, 3, 6, 8, 7, 2, 4};
void bubble_sort(int a[], int count)
{
int i, j;
for (i = 0; i < count; i++)
{
for (j = i+1; j < count; j++)
{
compexch(a[i], a[j]);
}
}
}
int main()
{
int i;
int count = sizeof(array)/sizeof(array[0]);
bubble_sort(array, count);
for (i = 0; i < count; i++)
{
printf("%d ", array[i]);
}
return 0;
}
代码分析:
1
2
3less-比较两个关键字
exch-交换两个元素
compexch-比较两个元素,并使第一个元素始终为最小
实现效果:
快速排序
特点:执行速度快
缺点:使用递归,消耗堆栈空间
实现过程:以一个元素为基准(通常是首元素),然后进行分区(比基准小得数放到左边,大的数放到右边;或反之),同样的方法对左边和右边进行分区,这里使用递归方法即可,以此下次进行排序,平均时间复杂度为O(NlgN)
C语言实现如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56#include
int a[] = {6,1,7,5,2,3,9,8,0,4};
void quickSort(int *a, int left, int right)
{
/*如果左边索引大于或者等于右边的索引就代表已经整理完成一个组了*/
if (left >= right) {
return;
}
int i = left;
int j = right;
int key = a[left];
/*控制在当组内寻找一遍*/
while (i < j) {
/*而寻找结束的条件就是,1,找到一个小于或者大于key的数(大于或小于取决于你想升
序还是降序)2,没有符合条件1的,并且i与j的大小没有反转*/
while ((i
j--; /*向前寻找*/
}
/*找到一个这样的数后就把它赋给前面的被拿走的i的值(如果第一次循环且key是
a[left],那么就是给key)*/
a[i] = a[j];
/*这是i在当组内向前寻找,同上,不过注意与key的大小关系停止循环和上面相反,
因为排序思想是把数往两边扔,所以左右两边的数大小与key的关系相反*/
while ((i=a[i])) {
i++;
}
a[j] = a[i];
}
/*当在当组内找完一遍以后就把中间数key回归*/
a[i] = key;
/*最后用同样的方式对分出来的左边的小组进行同上的做法*/
quickSort(a, left, i-1);
/*用同样的方式对分出来的右边的小组进行同上的做法*/
/*当然最后可能会出现很多分左右,直到每一组的i = j 为止*/
quickSort(a, i+1, right);
}
int main()
{
quickSort(a, 0, 9);
for (int i = 0; i < 10; ++i)
{
printf("%d ", a[i]);
}
return 0;
}
代码分析:
1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
2)以第一个数组元素作为关键数据,赋值给key,即key=a[0];
3)从j开始向前搜索,即由后开始向前搜索(j–),找到第一个小于key的值A[j],将A[j]和A[i]互换;
4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
5)重复第3、4步,直到i=j;(3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束),并把基数放到i==j时的A[i]处,实现左边的数比基数小,右边的数比基数大
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27以一个简单的数组为例:int a[] = {5,8,7,2,4};
代入上代码中运行,i = 0, j = 4, key = 5
| 0 | 1 | 2 | 3 | 4 |
| - | - | - | - | - |
| 5 | 8 | 7 | 2 | 4 |
经个第1次排序后,i = 1, j = 4, key = 5
| 0 | 1 | 2 | 3 | 4 |
| - | - | - | - | - |
| 4 | 8 | 7 | 2 | 8 |
经个第2次排序后,i = 2, j = 3, key = 5
| 0 | 1 | 2 | 3 | 4 |
| - | - | - | - | - |
| 4 | 2 | 7 | 7 | 8 |
经个第3次排序后,i = 2, j = 2, key = 5
| 0 | 1 | 2 | 3 | 4 |
| - | - | - | - | - |
| 4 | 2 | 5 | 7 | 8 |
此时i == j,将key赋值a[i],a[i] = 5
可以看出基数左边的数比基数小,右边的数比基数大
此时把左边和右边的数也按照上述步骤进行(使用递归),即可实现快速排序
实现效果:
源码下载