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

2023-12-24 12:36

本文主要是介绍《妙趣横生的算法》(C语言实现)-第2章 常用的查找与排序方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

// 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】折半查找数组中的元素。

// 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); // 查找成功 elseprintf("There is no %d in array A\n", n); // 查找失败 return 0;
}

总结:折半查找要考虑清楚上下界,是左闭右闭区间还是左闭右开区间。这和循环的终止条件有关。
【实例2-3】编写一个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】编程实现选择排序,要求从大到小排序,并输出序列。

// 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】编写程序实现冒泡排序,要求从大到小排序并输出元素。

// 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】编写程序实现希尔排序。

// 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】快速排序。

// 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]); // 交换位置elsebreak; }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;
}

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

这篇关于《妙趣横生的算法》(C语言实现)-第2章 常用的查找与排序方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/531795

相关文章

Nginx安全防护的多种方法

《Nginx安全防护的多种方法》在生产环境中,需要隐藏Nginx的版本号,以避免泄漏Nginx的版本,使攻击者不能针对特定版本进行攻击,下面就来介绍一下Nginx安全防护的方法,感兴趣的可以了解一下... 目录核心安全配置1.编译安装 Nginx2.隐藏版本号3.限制危险请求方法4.请求限制(CC攻击防御)

python生成随机唯一id的几种实现方法

《python生成随机唯一id的几种实现方法》在Python中生成随机唯一ID有多种方法,根据不同的需求场景可以选择最适合的方案,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习... 目录方法 1:使用 UUID 模块(推荐)方法 2:使用 Secrets 模块(安全敏感场景)方法

MyBatis-Plus通用中等、大量数据分批查询和处理方法

《MyBatis-Plus通用中等、大量数据分批查询和处理方法》文章介绍MyBatis-Plus分页查询处理,通过函数式接口与Lambda表达式实现通用逻辑,方法抽象但功能强大,建议扩展分批处理及流式... 目录函数式接口获取分页数据接口数据处理接口通用逻辑工具类使用方法简单查询自定义查询方法总结函数式接口

MySQL深分页进行性能优化的常见方法

《MySQL深分页进行性能优化的常见方法》在Web应用中,分页查询是数据库操作中的常见需求,然而,在面对大型数据集时,深分页(deeppagination)却成为了性能优化的一个挑战,在本文中,我们将... 目录引言:深分页,真的只是“翻页慢”那么简单吗?一、背景介绍二、深分页的性能问题三、业务场景分析四、

JAVA中安装多个JDK的方法

《JAVA中安装多个JDK的方法》文章介绍了在Windows系统上安装多个JDK版本的方法,包括下载、安装路径修改、环境变量配置(JAVA_HOME和Path),并说明如何通过调整JAVA_HOME在... 首先去oracle官网下载好两个版本不同的jdk(需要登录Oracle账号,没有可以免费注册)下载完

Spring StateMachine实现状态机使用示例详解

《SpringStateMachine实现状态机使用示例详解》本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解... 目录什么是状态机使用示例什么是状态机状态机是计算机科学中的​​核心建模工具​​,用于描述对象在其生命

Spring Boot 结合 WxJava 实现文章上传微信公众号草稿箱与群发

《SpringBoot结合WxJava实现文章上传微信公众号草稿箱与群发》本文将详细介绍如何使用SpringBoot框架结合WxJava开发工具包,实现文章上传到微信公众号草稿箱以及群发功能,... 目录一、项目环境准备1.1 开发环境1.2 微信公众号准备二、Spring Boot 项目搭建2.1 创建

IntelliJ IDEA2025创建SpringBoot项目的实现步骤

《IntelliJIDEA2025创建SpringBoot项目的实现步骤》本文主要介绍了IntelliJIDEA2025创建SpringBoot项目的实现步骤,文中通过示例代码介绍的非常详细,对大家... 目录一、创建 Spring Boot 项目1. 新建项目2. 基础配置3. 选择依赖4. 生成项目5.

深入理解Go语言中二维切片的使用

《深入理解Go语言中二维切片的使用》本文深入讲解了Go语言中二维切片的概念与应用,用于表示矩阵、表格等二维数据结构,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录引言二维切片的基本概念定义创建二维切片二维切片的操作访问元素修改元素遍历二维切片二维切片的动态调整追加行动态

Linux下删除乱码文件和目录的实现方式

《Linux下删除乱码文件和目录的实现方式》:本文主要介绍Linux下删除乱码文件和目录的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下删除乱码文件和目录方法1方法2总结Linux下删除乱码文件和目录方法1使用ls -i命令找到文件或目录