2. 排序
- 排序(sorting)
是把一个表 (通常表示为数组) 按某一次序重新排列。
2.1 对一个整数数组排序
考虑对一个整数数组排序的问题。
假设有一列以任意次序排列的整数数据,需要定义一个名为SortIntegerArray
的函数,使数组的元素按从小到大的顺序排列。
由于函数SortIntegerArray
要尽可能满足通用性,需要在函数中定义两个参数,即数组名和有效长度。
其原型为:
static void SortIntegerArray(int array[], int n);
2.2 选择排序算法
在众多的排序算法中,最容易理解的一种算法就是选择排序(selection sort)算法。
即,每次将其中的一个元素放在它最终要放的位置。
第一步是找到整个数组中的最小的元素并把它放在数组的起始位置,
第二步是在剩下的元素中找最小的元素并把它放在第二个位置上。
对整个数组重复这个过程,最终将得到按从小到大顺序排列的数组。
其中,由于不希望丢失某位置的原始值,最简单的办法是交换不同位置的值。
可以将上述过程用伪码表示:
![](https://i-blog.csdnimg.cn/blog_migrate/190774d151fb95453ccc07fde4417038.png)
在循环的最后,可以调用 前文reverse.c程序 里的SwapIntegerElements
函数来实现交换。
剩下一步就是找出最小值。按照逐步精化的原理, 可以定义一个新的函数来执行这个操作。
由此,可以实现SortIntegerArray
的代码:
void SortIntegerArray(int array[], int n) {
int lh, rh;
for (lh = 0; lh < n; lh++) {
rh = FindSmallestInteger(array, lh, n - 1);
SwapIntegerElements(array, lh, rh);
// printf("lh: %d, rh: %d\n", lh, rh);
}
}
函数FindSmallestInteger
存在三个参数:数组名和两个分别表示搜索范围的下标值,最终返回在指定下标位置间的最小值的下标。
其原型如下:
int FindSmallestInteger(int array[], int low, int high);
为了实现FindSmallestInteger
,最简单的方法是从头到尾检查表的元素,记录在每个循环周期中找到的最小值。当搜索到数组尾部时,这个最小值就是整个数组的最小值。
具体实现如下:
int FindSmallestInteger(int array[], int low, int high) {
int i;
int spos = low;
for (i = low; i <= high; i++) {
if (array[i] <= array[spos]) spos = i;
}
return spos;
}
其中,变量spos
保存最小值所对应的下标。
2.3 选择排序效率的评估
选择排序算法的优点之一,在于容易理解。
为了考量该算法的效率,需要确定用选择排序算法对某一输入数组进行排序需要多长时间。
存在两种方法可供参考:
(1) 可以运行该程序看它需要多少时间。
(2) 可以更一般地考虑程序的操作,对它的行为进行量化。
2.4 测试程序的运行时间
为了确定运行一个程序需要的时间,常用的方法是用系统库来记录所需要的时间。
ANSI接口time.h
输出一个名为clock
的过程,它能返回执行某一程序所用的以计算机处理单元为单位的时间量。
clock
函数返回的类型是与机器相关的时钟单位,但是可以通过以下的表达式将它转化成以秒来计算的时间形式:
![](https://i-blog.csdnimg.cn/blog_migrate/db11a4faabc1f5c16692157192d3118b.png)
如果把开始时间和结束时间分别存储于变量start
和finish
中,可以用下列代码计算执行一个操作所需的时间:
![](https://i-blog.csdnimg.cn/blog_migrate/5c2388875b513fa35effb248a8a6734e.png)
N
表示数组中元素的个数。
当N
很小时,选择排序算法需要的时间很少,但随着N
的增大,执行选择排序算法需要的时间显著增加。
最终,完整的sort.c
程序为:
#include <stdio.h>
#include <time.h>
#define N 10
/* Function Prototype */
static void SwapIntegerElements(int array[], int p1, int p2);
static int FindSmallestInteger(int array[], int low, int high);
static void SortIntegerArray(int array[], int n);
/* Main Program */
main() {
int j;
// int array[N]={0, 0, 2, 0, 4};
int array[N]={0, 70, 10, 20, 50, 40, 60, 30, 90, 80};
double start, finish, elapsed;
start = clock();
SortIntegerArray(array, N);
finish = clock();
printf("result: \n");
for (j = 0; j < N; j++) {
printf("%d\n", array[j]);
}
elapsed = (finish - start) / CLOCKS_PER_SEC;
printf("cost time: %.4f ms\n", (elapsed*1000));
}
/* Function */
static void SortIntegerArray(int array[], int n) {
int lh, rh;
for (lh = 0; lh < n; lh++) {
rh = FindSmallestInteger(array, lh, n - 1);
SwapIntegerElements(array, lh, rh);
// printf("lh: %d, rh: %d\n", lh, rh);
}
}
static void SwapIntegerElements(int array[], int p1, int p2) {
int tmp;
tmp = array[p1];
array[p1] = array[p2];
array[p2] = tmp;
}
static int FindSmallestInteger(int array[], int low, int high) {
int i;
int spos = low;
for (i = low; i <= high; i++) {
if (array[i] <= array[spos]) spos = i;
}
return spos;
}
result:
0
10
20
30
40
50
60
70
80
90
cost time: 0.0020 ms
参考
《C语言的科学和艺术》 —— 第12章 查找和排序