(十二)查找和排序 -- 2. 排序

2. 排序

  • 排序(sorting)
    是把一个表 (通常表示为数组) 按某一次序重新排列。

2.1 对一个整数数组排序

考虑对一个整数数组排序的问题。

假设有一列以任意次序排列的整数数据,需要定义一个名为SortIntegerArray的函数,使数组的元素按从小到大的顺序排列。

由于函数SortIntegerArray要尽可能满足通用性,需要在函数中定义两个参数,即数组名和有效长度。

其原型为:

static void SortIntegerArray(int array[], int n);

2.2 选择排序算法

在众多的排序算法中,最容易理解的一种算法就是选择排序(selection sort)算法。

即,每次将其中的一个元素放在它最终要放的位置。

第一步是找到整个数组中的最小的元素并把它放在数组的起始位置,
第二步是在剩下的元素中找最小的元素并把它放在第二个位置上。

对整个数组重复这个过程,最终将得到按从小到大顺序排列的数组。

其中,由于不希望丢失某位置的原始值,最简单的办法是交换不同位置的值。


可以将上述过程用伪码表示:

在循环的最后,可以调用 前文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函数返回的类型是与机器相关的时钟单位,但是可以通过以下的表达式将它转化成以秒来计算的时间形式:

如果把开始时间和结束时间分别存储于变量startfinish中,可以用下列代码计算执行一个操作所需的时间:

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章 查找和排序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值