《妙趣横生的算法》(C语言实现)-第2章 常用的查找与排序方法

【实例2-1】一个结构体数组中存放的是学生记录,每条记录包括:学号、姓名、成绩。编写一个程序,要求输出1001编号同学的具体信息。

c 复制代码
// 2-1 2023年12月23日18点05分-18点14分 
typedef struct student{ // 定义学生结构体类型 
    int id; // 学生编号
    char name[10]; // 学生姓名
    float score; // 学生成绩 
}Student;
int search(Student stu[], int n, int key)
{
    for (int i = 0; i < n; ++i) {
        if (stu[i].id == key) // 查找成功 
            return i;
    }
    return -1; // 查找失败 
}
# include <stdio.h>
int main()
{
    Student stu[4] = {{1004, "TOM", 100}, {1002, "LILY", 95}, 
                      {1001, "ANN", 93}, {1003, "LUCY", 98}}; // 初始化结构体数组
    // 顺序查找1001编号同学的具体信息
    int addr; // 要查找的记录的地址
    addr = search(stu, 4, 1001); 
    printf("Student ID:   %d\n", stu[addr].id); // 输出查找到的记录的信息
    printf("Student name: %s\n", stu[addr].name); 
    printf("Student score: %f\n", stu[addr].score);
    return 0;
} 

总结:顺序查找的优点在于简单直观,对于被查找的记录在文件中的排列顺序没有限制,因此比较适合顺序文件的查找。同时这种查找思想也适合于对顺序表数据结构和链表数据结构中的元素进行查找。它的缺点在于平均查找长度过大,查找效率低。逐个依次查找。

【实例2-2】折半查找数组中的元素。

c 复制代码
// 2-2 2023年12月23日18点28分-
# include <stdio.h>
int bin_search(int A[], int n, int key)
{
    int low = 0, high = n - 1, mid;
    while (low <= high) {
        mid = (low + high) / 2; // 设置mid的值 
        if (A[mid] == key) {
            return mid; // 查找成功,返回mid
        }
        if (A[mid] < key) { 
            low = mid + 1; // 在后半序列中查找 
        }
        if (A[mid] > key) {
            high = mid - 1; // 在前半序列中查找 
        }
    }
    return -1; // 查找失败,返回-1 
}
int main()
{
    int A[10] = {2, 3, 5, 7, 8, 10, 12, 15, 19, 21};
    printf("The contents of the array A[10] are\n");
    for (int i = 0; i < 10; ++i)
        printf("%d ", A[i]); // 显示数组A中的内容
    int n;
    printf("\nPlease input a integer for search\n");
    scanf("%d", & n); // 输入待查找的元素
    int addr = bin_search(A, 10, n); // 折半查找,返回该元素在数组中的下标
    if (-1 != addr)
        printf("%d is at the %dth unit in array A\n", n, addr + 1); // 查找成功 
    else
        printf("There is no %d in array A\n", n); // 查找失败 
    return 0;
}

总结:折半查找要考虑清楚上下界,是左闭右闭区间还是左闭右开区间。这和循环的终止条件有关。

【实例2-3】编写一个C程序,实现直接插入排序,要求从大到小排序,并输出排序后的数列元素。

c 复制代码
// 2-3 2023年12月23日18点59分-19点09分 
void insertsort(int A[], int n)
{
    for (int i = 1; i < n; ++i) {
        int tmp = A[i]; // 将A[i]保存在临时变量tmp中
        int j = i - 1;
        while (j >= 0 && tmp > A[j]) { // 找到tmp的插入位置 
            A[j + 1] = A[j--]; // 将A[j]后移,再将j减1 
        }
        A[j + 1] = tmp; // 将元素tmp插入到指定位置,第i趟排序完成 
    }
}
# include <stdio.h> 
int main()
{
    int a[] = {-111, 2, 5, 6, 3, 7, 8, 0, 9, 12, 1}; // 初始化序列 
    printf("The original data array is\n");
    for (int i = 0; i < sizeof(a) / sizeof(int); ++i)
        printf("%d ", a[i]); // 显示原序列之中的元素 
    insertsort(a, sizeof(a) / sizeof(int)); // 插入排序 
    printf("\nThe result of insertion sorting for the array is\n");
    for (int i = 0; i < sizeof(a) / sizeof(int); ++i)
        printf("%d ", a[i]);
    return 0;
}

总结:插入排序,一个包含n个元素的序列,需要(n-1)趟排序,就可以使得这个序列有序。因为如果只包含一个元素肯定有序,如果包含两个及以上元素,那么就需要比较(n-1)次。

【实例2-4】编程实现选择排序,要求从大到小排序,并输出序列。

c 复制代码
// 2-4 2023年12月23日19点22分-19点34分 
void selectionsort(int A[], int n) // 选择排序 
{
    for (int i = 0; i < n - 1; ++i) {
        int max = i;
        for (int j = i + 1; j < n; ++j) { // 在后(n-i)个元素中找到最大的元素位置 
            if (A[j] > A[max]) {
                max = j; // 用max记录下最大元素的位置 
            }
        }
        if (max != i) { // 如果最大的元素不位于后(n-i)个元素第1个 
            int tmp = A[max]; // 元素的交换 
            A[max] = A[i];
            A[i] = tmp;
        }
    }
} 
# include <stdio.h>
int main()
{
    int a[] = {-111, 2, 5, 6, 3, 7, 8, 0, 9, 12, 1}; // 初始化序列 
    printf("The original data array is\n");
    for (int i = 0; i < sizeof(a) / sizeof(int); ++i) {
        printf("%d ", a[i]); // 显示原序列的元素 
    }
    selectionsort(a, sizeof(a) / sizeof(int)); // 执行选择排序 
    printf("\nThe result of selection sort for the array is\n");
    for (int i = 0; i < sizeof(a) / sizeof(int); ++i) {
        printf("%d ", a[i]); // 输出排序后的结果 
    }
    return 0;
}

总结:选择排序,一个包含n个元素的序列需要(n-1)趟排序。每次找最小或者最大的元素放在前面位置。

【实例2-5】编写程序实现冒泡排序,要求从大到小排序并输出元素。

c 复制代码
// 2-5 2023年12月23日19点42分-19点47分 
//void bubblesort(int A[], int n) // 冒泡排序 
//{
//    for (int i = n - 1; i > 0; --i) {
//        for (int j = 0; j < i; ++j) {
//            if (A[j] < A[j + 1]) {
//                int tmp = A[j];
//                A[j] = A[j + 1];
//                A[j + 1] = tmp;
//            }
//        }
//    }
//} 
void bubblesort(int A[], int n) // 改进的冒泡排序 
{
    int flg = 1;
    for (int i = n - 1; i > 0 && flg == 1; --i) {
        flg = 0;
        for (int j = 0; j < i; ++j) {
            if (A[j] < A[j + 1]) {
                int tmp = A[j];
                A[j] = A[j + 1];
                A[j + 1] = tmp;
                flg = 1; // 发生数据交换flg置1 
            }
        }
    }
} 
# include <stdio.h>
int main()
{
    int a[] = {-111, 2, 5, 6, 3, 7, 8, 0, 9, 12, 1}; // 初始化序列 
    printf("The original data array is\n");
    for (int i = 0; i < sizeof(a) / sizeof(int); ++i)
        printf("%d ", a[i]); // 显示原序列 
    bubblesort(a, sizeof(a) / sizeof(int)); // 执行冒泡排序 
    printf("\nThe result of bubble sort of this array is\n");
    for (int i = 0; i < sizeof(a) / sizeof(int); ++i)
        printf("%d ", a[i]); // 输出排序后的结果 
    return 0;
}

总结:冒泡排序,一个包含n个元素的序列需要(n-1)趟排序。每次确定了一个最大元素,冒泡冒出来的。改进后的冒泡排序算法可以减少排序时的比较次数,提高冒泡排序的效率。

【实例2-6】编写程序实现希尔排序。

c 复制代码
// 2-6 2023年12月23日20点01分-20点10分
void shellsort(int A[], int n) // 希尔排序 
{
    int gap = n;
    int flg, j;
    while (gap > 1) {
        gap /= 2; // 增量缩小,每次减半
        do { // 子序列应用冒泡排序 
            flg = 0;
            for (int i = 1; i <= n - gap; ++i) {
                j = i + gap;
                if (A[i] < A[j]) {
                    int tmp = A[i];
                    A[i] = A[j];
                    A[j] = tmp;
                    flg = 1;
                }
            } 
        } while (flg != 0); 
    } 
} 
# include <stdio.h>
int main()
{
    int a[] = {-111, 2, 5, 6, 3, 7, 8, 0, 9, 12, 1}; // 初始化序列 
    printf("The original data array is\n");
    for (int i = 0; i < 10; ++i)
        printf("%d ", a[i+1]); // 显示原序列 
    shellsort(a, 10); // 执行希尔排序 
    printf("\nThe result of bubble sort of this array is\n");
    for (int i = 0; i < 10; ++i)
        printf("%d ", a[i+1]); // 输出排序后的结果 
    return 0;
}

【实例2-7】快速排序。

c 复制代码
// 2-7 2023年12月23日20点13分-20点21分 
void swap(int * a, int * b) // 序列中元素位置的交换 
{
    int tmp = * a;
    * a = * b;
    * b = tmp;
}
void quicksort(int A[], int s, int t)
{
    if (s < t) {
        int i = s, j = t + 1;
        while (1) {
            do {
                ++i;
            } while (!(A[s] >= A[i] || i == t)); // 重复执行++i操作
            do {
                --j;
            } while (!(A[s] <= A[j] || j == s)); // 重复执行--j操作
            if (i < j)
                swap(& A[i], & A[j]); // 交换位置
            else
                break; 
        }
        swap(& A[s], & A[j]); // 交换基准元素与A[j]的位置 
        quicksort(A, s, j - 1); // 递归排序基准元素前面的子序列 
        quicksort(A, j + 1, t); // 递归排序基准元素后面的子序列 
    }
}
# include <stdio.h>
int main()
{
    int a[] = {2, 5, 6, 3, 7, 8, 0, 9, 12, 1}; // 初始化序列 
    printf("The original data array is\n");
    for (int i = 0; i < sizeof(a) / sizeof(int); ++i) {
        printf("%d ", a[i]); // 显示原序列的元素 
    }
    quicksort(a, 0, sizeof(a) / sizeof(int) - 1); // 执行快速排序 
    printf("\nThe result of selection sort for the array is\n");
    for (int i = 0; i < sizeof(a) / sizeof(int); ++i) {
        printf("%d ", a[i]); // 输出排序后的结果 
    }
    return 0;
}

总结:这个程序有问题,尚在寻找中。

相关推荐
JingHongB5 分钟前
代码随想录算法训练营Day55 | 图论理论基础、深度优先搜索理论基础、卡玛网 98.所有可达路径、797. 所有可能的路径、广度优先搜索理论基础
算法·深度优先·图论
weixin_432702268 分钟前
代码随想录算法训练营第五十五天|图论理论基础
数据结构·python·算法·深度优先·图论
小冉在学习10 分钟前
day52 图论章节刷题Part04(110.字符串接龙、105.有向图的完全可达性、106.岛屿的周长 )
算法·深度优先·图论
Repeat71511 分钟前
图论基础--孤岛系列
算法·深度优先·广度优先·图论基础
小冉在学习13 分钟前
day53 图论章节刷题Part05(并查集理论基础、寻找存在的路径)
java·算法·图论
武子康25 分钟前
大数据-212 数据挖掘 机器学习理论 - 无监督学习算法 KMeans 基本原理 簇内误差平方和
大数据·人工智能·学习·算法·机器学习·数据挖掘
passer__jw7671 小时前
【LeetCode】【算法】283. 移动零
数据结构·算法·leetcode
Ocean☾1 小时前
前端基础-html-注册界面
前端·算法·html
顶呱呱程序1 小时前
2-143 基于matlab-GUI的脉冲响应不变法实现音频滤波功能
算法·matlab·音视频·matlab-gui·音频滤波·脉冲响应不变法
TeYiToKu1 小时前
笔记整理—linux驱动开发部分(9)framebuffer驱动框架
linux·c语言·arm开发·驱动开发·笔记·嵌入式硬件·arm