news 2026/10/29 2:17:34

第8-9周:C语言数组算法练习

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第8-9周:C语言数组算法练习

在这一周,我学习了在数组中求最值,求和(基础和升级),打乱数组的数据,反转数组,查找(其中分基本查找,二分查找,分块查找,哈希查找),还学习了排序(冒泡排序和选择排序),除此之外,我还练习了题目,结合三大结构,函数,数组,包括下列查找,排序

首先先回顾一下,数组是一个什么东西。数组是一种容器,可以用来存储同个数据类型的多个值。

求最值:

1.需要定义数组,
2.定义变量max:max的默认值一定是数组中存在的数据,一般将索引0当作默认值,
3.然后利用循环遍历数组,遍历数组得到的每一个元素,与max比较。

//1.定义数组 int num[] = { 33,5,22,44,55 }; int len = sizeof(num) / sizeof(int); //2.定义变量表示max int max = num[0]; //3.利用循环遍历数组,遍历数组得到每一个元素,拿着遍历得到的元素与max比较 for (int i = 1;i < len;i++) { if (num[i] > max) { max = num[i]; } } //4.输出打印 printf("%d\n", max);

求和:

求和分为基础和升级,二者的区别在于,基础版可以数据重复,但是升级版不可以,所以应保证每一个元素只出现一次。
无论是基础还是升级,我们都用到随机数。如何得到随机数,我们应设置种子,再生成随机数。
既然升级版数据不可以重复,那在代码上二者的区别;升级多了一步判断随机数存在数组中之前应判断,刚生成的随机数是否已存在于数组中,我们可以利用函数判断随机数是否在数组中存在。

这里的代码只展示判断num与数组中的数据是否重复

//设置种子,生成10个 1到10 之间的随机数 srand(time(NULL)); //生成随机数 此时for后面的i++在下面,这意味着,循环变量i不会每次循环都自动加1 for (int i = 0;i < len;) //i=0时给arr[0]-arr[9]赋值 { int num = rand() % 10+1 ; //把随机数num存入数组中,但存入之前需要判断,判断刚刚生成的随机数是否已经存在于当前的数组中 int flag = contains(arr, len, num); if (!flag) //!flag: 如果flag为假,则flag==0,也就是不存在的意思 { arr[i] = num; //把目前num存入数组第i个位置 i++; //只有符合if里面的语句,才会加1 }
//判断num在函数中是否存在 //存在,返回1 //不存在,返回0 int contains(int arr[],int len,int num) { for (int i = 0;i < len;i++) //i:依次表示数组中每一个索引 { //arr[i];依次表示数组中每一个数据 if (arr[i]==num) { return 1; } } return 0; }

打乱数组中的数据;

核心原理是:遍历数组,将当前遍历到的元素与数组中随机位置的一个元素进行交换。
其中int index = rand() % len;作用是生成随机下标。rand() 会生成一个很大的随机数,通过 % len(取余数),可以将这个随机数限制在 0 到 len-1 的范围内(即 0 到 4),得到的就是一个随机的数组下标。

//1.定义数组 int arr[] = { 1,2,3,4,5, }; int len = sizeof(arr) / sizeof(int); //2.遍历数组(用于打乱数据),得到数组每一个元素,让这个元素跟随机索引进行交换 //设置种子 srand(time(NULL)); for (int i = 0;i < len;i++) { //获取一个随机索引(随机数) //min;0 max;4 int index = rand() % len; //rand是一个函数,作用是生成一个很大的随机数,所以我们要控制随机数的范围, //拿着i指向的元素,跟index指向的元素进行交换 int temp = arr[i]; arr[i] = arr[index]; arr[index] = temp; } //3.遍历数组(用于打印输出)省略...

反转数组;

核心原理是:双指针法(首尾指针向中间靠拢)。在反转数组中用到的循环结构是while。其中while (i < j),括号中是条件判断语句(循环条件),只要左指针还在右指针的左边,就说明还没有相遇,需要继续交换。一旦 i >= j(相遇或者交叉),说明整个数组已经反转完毕,循环结束。
如何判断用for还是while:
1.已知循环次数或循环范围,用 for 循环更清晰。
2. 如果是不知道循环次数或循环范围,只知道结束条件,用 while 循环更合适。

//4.反转数组 int i = 0; int j = len-1; while (i < j) //用for循环过于繁琐,即使我们知道需要循环多少次(len/2次), //但这种“左右两边同时移动”的逻辑中,什么时候停取决于两边的相遇,而不是单纯的要循环多少次 //并且如何选择for还是while: //1.当知道循环次数或范围用for; //2.不知道循环次数或范围用while, / 而循环的终止条件依赖于多个变量动态变化时,while比for更适合 { int temp = num[i]; num[i] = num[j]; num[j] = temp; i++; // 双指针向中间靠拢,如果不打这两步,i和j不懂,变成死循环,还是在同样的位置互换 j--; } //5.遍历数组 printArr(num, len);

查找:

基本查找,二分查找,插值查找,分块查找,哈希查找,

①基本查找(顺序查找):从头到尾遍历数组。
核心思路:从数组0索引开始依次往后查找。
如果找到了,就会返回数组中的索引。
如果没找到,就会返回-1。

//1.定义数组 int arr[] = { 23,52,34,89,16 }; int len = sizeof(arr) / sizeof(int); //2.定义一个变量表示要查找的数据 int num = 34; //3.调用函数查找数据 int index=order(arr, len, num); //4.输出索引 printf("%d\n", index); return 0; } //函数作用:查找数组中的数据 //返回值;数据所在的索引, int order(int arr[], int len, int num) { for(int i = 0;i < len;i++) { if (arr[i] == num) { return i; } } return -1; }

②二分查找(折半查找):
使用前提条件:
数组中的数据必须是有序,可以是从小到大也可以是哦从大到小,就是不可以是乱的。
核心思路:每次排除一半的查找范围
1.定义min和max,表示当前的查找范围
2.定义mid,mid在min和max中间,mid=(min+max)/2
3.如果要查找的数据在mid左边,则min不变,max=mid-1
如果要查找的数据在mid右边,则max不变,min=mid+1

//1.定义数组 int arr[] = { 12,25,37,58,60,67,82,92 }; int len = sizeof(arr) / sizeof(int); //2.定义一个变量表示要查找的数据 int num = 82; //3.调用函数查找数据 int index = binaryserach(arr, len, num); //4.输出索引 printf("%d\n", index); return 0; } //函数作用;利用二分查找查找数据 //返回值:数据在数组中的索引 //找到了, 就会返回数据对应的索引 //没找到,就会返回-1 int binaryserach(int arr[], int len, int num) { //1.确定查找范围 int min = 0; int max = len - 1; //2.利用循环不断进行查找 while (min <= max) { //确定中间位置 int mid = (min+max)/ 2; //进行比较,此时min、mid、max都表示数组的索引 //而此时的num表示要查找的元素,所以一定要拿arr[mid]跟num比较 //判断 if (arr[mid] < num) //要查找的num在右边,则max不变,min为mid+1 { min = mid + 1; } else if (arr[mid] > num) //要查找的num在左边,则min不变,max为mid-1 { max = mid - 1; } else { return mid; } //3.如果min大于max了,表示数据不存在,返回-1 return -1; }

③插值查找:
使用前提条件:
数据有序,且数据分布尽可能均匀一点
它与二分查找操作差不多,只要把mid的表达式换一下就好了
mid=min+(key-arr【min】)/(arr【max】-arr【min】)*(max-min)
它对于二分查找的优势:效率比二分查找快,但如果前提条件不符,还会适得其反

代码不展示,与二分查找一样,只需把mid的表达式换一下即可

//确定中间位置 int mid = min + (key - arr[min]) / (arr[max] - arr[min]) * (max - min); //可以直接用num,没必要多余定义key

④分块查找:
核心思路:先确定要查找的元素在哪一块,然后在其块内挨个查找。
如何分块,分块原则:
• 块内无序:每一个小块内部的数据,可以是乱序的(不需要排序)。
• 块间有序:第 1 块中的最大值,必须小于第 2 块中的最小值;第 2 块的最大值,必须小于第 3 块的最小值……以此类推。(即整体趋势是递增的)。
一般块数的数量等于数据个数的开根号(eg:16个数据一般分为4块)
且需要注意,分块中每一块的数据范围不可以有交集

⑤哈希查找:
核心思路:把数据存入时,通过公式计算出一个位置(哈希值);查找时,用同样的公式算出位置,直接去那个位置取数据。
它和另外四个查找不一样,它不找数据,而是直接算出数据的位置。

排序算法:

冒泡排序,选择排序

①冒泡排序:
核心思路:1.相邻的数据两两比较,小的放前面,大的放后面。(大的放右,小的放左)
2.第一轮循环结束,最大的已经在最右边,放在数组最右边。
3.剩余数据继续循环排序。
如果数组中有n个数据,总共我们只要执行 n-1 轮代码即可。

//2.利用冒泡排序,将数组中的数据进行升序排序 //我们可以发现四轮下来,只有条件判断语句那一部分变动了,所以我们可以在套一个循环,使它变得简便 一; for (int i = 0;i < len -1;i++) // i:范围0,1,2,3, 此时条件判断语句要写len-1,防止索引越界 //外循环:控制比较的轮数 //随着i的增加,内循环范围越来越小 { //内循环:控制每一轮的次数 //j:表示进行比较的元素下标 //每过一轮,就会有一个最大的数排到末尾,所以后面的数就不用比较了则-i for (int j = 0;j < len - 1-i;j++) { //相邻元素二二比较,小的在前,大的在后 //j与j+1比较 if (arr[j] > arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } }

利用冒泡排序,解决方法:双重循环
双重循环本质:指内循环重复执行n次。
内循环:找到本次循环的较大值,再把较大值放到最右边。
外循环:把这个动作执行n次。

②选择排序:
核心思路:
1.索引0开始,拿着每一个索引上的元素跟后面元素依次比较,小的放前面,大的放后面。
2.第一轮循环结束,最小值已经找到,放在数组最左边
3.第二轮循环从索引1开始依次比较。依次类推…

//2.利用选择排序,将数组中的数据进行升序排序 //第一轮: i=0,j=1,2,3,4, // 第二轮,i=1,j=2,3,4, // 第三轮,i=2,j=3,4, // 第四轮,i=3,j=4, //i;依次表示数组中每一个索引 for (int i = 0;i < len - 1;i++) //i<len-1,防止索引越界 { //j;依次表示i索引后面的每一个索引 for (int j = i + 1;j < len;j++) //假如第一轮比较结束,它会直接将比索引0小的互换位置 { //判断的代码逻辑是: 拿着 arr[i] 去和后面所有元素相比,只要遇到比它小的,当场就换, 一轮下来,最小的那个必定会通过多次交换,“顶”到 i 的位置上。 if (arr[i] > arr[j]) //如果成立,则互换位置 { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } }

冒泡排序VS选择排序
核心动作:相邻两两比较,频繁交换 找最小/最大值,一轮只换一次
适用场景:数据量极少 数据量极少

算术练习

回文数

斐波那契数列

水仙花数

综合练习

1.

2.

3.

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/29 2:17:07

绿色工厂申报反复卡壳?很多企业都栽在台账和数据协同上

做制造企业的朋友应该都有同感&#xff1a;申报绿色工厂&#xff0c;最难的从来不是写申报材料&#xff0c;而是把分散在车间、财务、设备、运维各个角落的数据收拢对齐。 不少工厂前期准备很久&#xff0c;自评表填得满满当当&#xff0c;现场专家一核查&#xff0c;问题立刻…

作者头像 李华
网站建设 2026/10/29 2:16:40

记录|程序员的月底复盘:清理代码Bug,也清理牙齿问题

又到了月底复盘的时候。平时复盘的都是项目进度和代码Bug&#xff0c;今天想了想&#xff0c;也该复盘一下自己的身体了。毕竟&#xff0c;身体才是革命的本钱。翻了翻自己的备忘录&#xff0c;发现有一项叫“洗牙”的任务一直挂在上面。平时加班多&#xff0c;周末总想躺着&am…

作者头像 李华
网站建设 2026/10/29 2:15:15

实验室用等离子表面处理设备处理消费电子小件的一点记录

最近帮朋友测了几组消费电子常用小件&#xff0c;用实验室那台等离子表面处理设备处理了一下&#xff0c;记录点数据。材料一&#xff1a;ABS耳机外壳。处理前达因值大概32 dyn/cm&#xff0c;喷涂PU漆后缩孔明显&#xff0c;百格2B—3B、边缘剥落。常压等离子处理后达因值到68…

作者头像 李华
网站建设 2026/10/29 2:14:19

大模型赋能搜推:小白程序员必看!收藏这份电商大模型学习指南

电商行业正经历深刻变革&#xff0c;大模型技术为搜推技术带来智能化和个性化的飞跃。文章分析了电商场景下大模型的应用问题&#xff0c;如商品知识理解、效果和个性化、时效性、成本和速度以及安全性等。同时&#xff0c;文章详细介绍了京东在大模型电商场景下的解决方案&…

作者头像 李华
网站建设 2026/10/29 2:11:53

编程没有被取代,被取代的是“写代码“这件事本身

从 Sam Altman 与 Matthew Berman 的 45 分钟访谈&#xff0c;看软件需求弹性、能力迁移与手艺的消失关于 AI 与程序员的关系&#xff0c;过去两年流行过两个截然相反的预言。第一个是"AI 会让开发者失业"&#xff1b;第二个是"AI 只是工具&#xff0c;程序员照…

作者头像 李华
网站建设 2026/10/29 2:11:34

CFB密文反馈模式期末专项突破:s-bit CFB核心考点全解析

&#x1f393; CFB密文反馈模式期末专项突破&#xff1a;s-bit CFB核心考点全解析&#x1f4dd; 摘要&#xff1a;本文适配郭亚军《信息安全技术》教材&#xff0c;针对期末考试中 CFB&#xff08;密文反馈&#xff09;模式 的高频考点进行专项梳理。涵盖核心公式、1-bit CFB工…

作者头像 李华