C语言入门——第十七课

一、二分查询

1.概念

二分查询又被称为二分查找,是一种在有序数组或序列中快速查找到对应元素的一种方法。每次查找范围缩小至原来的一半。

①前提条件

数组和列表必须有序,否则无法进行二分查找。

②初始化

确定查找数组和列表的左边界(通常为数组或列表第一个元素)和右边界(通常为数组和列表最后一个元素)。

③循环

  • 计算中间元素的序列
  • 比较中间元素和目标元素
    • 如果中间元素等于目标元素,那么查询结束,返回中间元素的索引。
    • 如果目标元素大于中间元素,说明目标元素在中间元素的右半部分,那么左边界移到中间元素的右边。
    • 如果目标元素小于中间元素,说明目标元素在中间元素的左半部分,那么右边界移至中间元素的左边。

④结束条件

如果查找到目标元素的索引,退出。

或者如果左边元素的索引大于右边元素,说明目标元素不在数组内,那么退出。 

2.代码

int BinaryFindValue(const int* arr, int n, int value)
{int pos = -1;if (n < 1 || arr == NULL)	return pos;int left = 0;int right = n-1;while (left<=right){int mid = (right - left +1 ) / 2 + left;if (value < arr[mid]){right = mid - 1;}else if (value > arr[mid]){left = mid + 1;}else{pos = mid;break;}} return pos;
}
int main()
{const int n = 5;int arr[n] = { 10,11,12,13,14 };int val = 0;scanf("%d", &val);int m = BinaryFindValue(arr, n, val);printf("%d", m);
}

也可以将这一行写成这样

int mid = (right - left +1 ) / 2 + left;

修改后: 

int mid = (right - left + 1) >> 1 + left;

 >> 是右移位操作符,在计算机中执行二进制位的右移。>> 1 表示将二进制位向右移动一位,相当于除以2。

注意这里有个问题:

int mid =((right - left + 1) >> 1) + left;

加号大于右移操作符,这样写的话是1+left然后右移,所以要给前面加上括号。

最终正确代码

int BinaryFindValue(const int* arr, int n, int value)
{int pos = -1;if (n < 1 || arr == NULL)	return pos;int left = 0;int right = n-1;while (left<=right){int mid = ((right - left + 1) >> 1) + left;if (value < arr[mid]){right = mid - 1;}else if (value > arr[mid]){left = mid + 1;}else{pos = mid;break;}} return pos;
}
int main()
{const int n = 5;int arr[n] = { 10,11,12,13,14 };int val = 0;scanf("%d", &val);int m = BinaryFindValue(arr, n, val);printf("%d", m);
}

3. Q&A

Q:下面这个代码有问题,请详细说明原因

A:

问题一:是left<right判断条件,如果目标值是右边界值的话没有办法正确输出值。具体看下面的图示。

问题二:是使用(left+right)/2,如果left和right足够大,他们的mid很可能超出最大整数的范围,容易溢出。

修改:

① 修改判断条件,让left<=right的时候退出循环,这样就可以查找到边界的目标元素。

②修改查找中间元素的计算方式,所以使用下面的方式只对区域进行取半。

4.优化一

如果我的序列中有多个重复的数字,我想要找到最左端数字的下标,你需要怎么做?

添加一个判断

while (arr[mid - 1] == value){mid--;}pos = mid;break;

判断arr[mid]和value相等的时候,它的前一个值是否也相等,但是这样写是错误的,因为如图,在下面的示例中,要找到12最左边元素的下标值,mid-1判断到mid=0下标的时候,再-1会造成越界,所以我们要对于判断条件增加。

增加一个条件mid-1>=0,防止越界行为,老师在这里增加的条件是mid>left,也是相同的道理,两种写法都可以。 

//while ((mid>left) && (arr[mid - 1] == value))
while ((mid-1 >= 0) && (arr[mid - 1] == value)){mid--;}pos = mid;break;
int BinaryFindValue(const int* arr, int n, int value)
{int pos = -1;if (n < 1 || arr == NULL)	return pos;int left = 0;int right = n-1;while (left<=right){int mid =((right - left + 1) >> 1) + left;if (value < arr[mid]){right = mid - 1;}else if (value > arr[mid]){left = mid + 1;}else{while ((mid-1 >= 0) && (arr[mid - 1] == value)){mid--;}pos = mid;break;}} return pos;
}
int main()
{const int n = 13;int arr[n] = { 12,12,12,13,13,13,13,13,24,24,24,25,26};int val = 0;scanf("%d", &val);int m = BinaryFindValue(arr, n, val);printf("%d", m);
}

5.优化二

在这里查找最左端元素的时候,你使用的是递归查询,请问怎么样使用二分法继续进行最左端元素的查找。

使用递归方法继续查找呢?

暂无思路,待补充……

二、结构体

1.定义

结构体是由我们自己设计的一种类型。

结构体和数组的区别:数组中所有元素的类型一致,但是结构体中元素的类型不需要一致。

结构体的定义

struct Student //结构体名
{
    //成员列表
};

这里结束的时候记得写分号哦!

注意: 在C语言中,这里的Student是结构体名,struct Student是结构体类型名。在进行创建结构体变量时,需要使用结构体类型名创建。但是在C++中结构体类型名和结构体名没有区别。

Student sx;//错误
struct Student sx;//正确 

2.初始化 

结构体的在声明的时候不需要初始化,因为它此时还是类型,不会开辟空间,所以不能赋初值。在定义结构体变量时,系统才会给结构体分配空间。

初始化顺序需要与结构体声明次序保持一致。

①使用花括号初始化

struct Student
{char s_name[20];int age;
};
int main()
{struct Student sx = { "lizeyu",23 };printf("%s %d\n", sx.s_name, sx.age);
}

结构体嵌套结构体初始化,也是使用花括号初始化。

struct Date
{int year;int month;int day;
};
struct Student
{char s_name[20];Date birthday;int age;
};
int main()
{struct Student sx = { "lizeyu",{2000,8,21},23 };printf("%s %d\n", sx.s_name, sx.age);
}

或者写成这个样子也是可以的:

struct Student sx = { "lizeyu",2000,8,21,23 };

3.结构体在内存中的存储

如果结构体内的数组是按照[ ]方式声明的,定义变量的时候,栈区为数组分配对应字节的空间。

如果声明结构体成员列表的时候使用指针的方式声明数组,那么栈区的指针指向被存储在.data区的数组。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C盘变红怎么办?一个快速解决C盘快满的方法

前情提要 通常解决C盘快满的方法是&#xff1a; 找到C盘—右击选择“属性”—选择“详细信息”—卸载不常用的软件或者清除临时文件 缺点&#xff1a;成效甚微 今日重点 1.背景知识&#xff1a;微信是我们日常工作和生活都离不开的工具&#xff0c;我们每天使用微信会产生大量…

Mendix与Java组件的完美结合实践

前言 在技术驱动的今天&#xff0c;应用开发的速度和质量已经成为企业竞争力的决定性因素。Mendix&#xff0c;作为一款领先的低代码开发平台&#xff0c;已经为全球数千家企业提供了快速、高效的开发解决方案。但在某些情况下&#xff0c;企业的特定需求可能超出了Mendix的标…

sqli-labs(3)

11. 看到登录框直接or 11 在hackerabar中我们可以看到这里是post传递的数据&#xff0c;在get中用--来注释后面的内容 因为get中#是用来指导浏览器动作的&#xff0c;--代表注释是空格&#xff0c;所以这里用# 之后就和get的一样了 1 order by 2 # order by 3报错 联合注入 …

21款奔驰GLS450升级23P驾驶辅助 提升安全出行

辅助驾驶越来越多的被大家所青睐&#xff01;为了提升驾驶安全性和舒适便捷性奔驰改装原厂半自动驾驶23P辅助系统 23P智能辅助驾驶系统还是很有必要的&#xff0c;因为在跑高速的时候可以使用23P智能驾驶的自动保持车速&#xff0c;保持车距&#xff0c;车道自动居中行驶以及自…

CRM商机管理软件:构建客户为中心的管理理念

企业为什么选择CRM商机管理软件&#xff1f;1.CRM软件能够帮助企业建立以客户为中心的管理理念&#xff1b;2.CRM商机管理软件全面直观的展示客户数据&#xff1b;3.市场人员可以制订个性化的营销策略&#xff1b;4.移动应用为外出的销售带来的便利。 1.构建客户为中心的管理理…

C++实现KNN和K-Means

学校机器学习课程的实验课要求实现KNN和K-Means&#xff1a; &#xff08;平时没听课&#xff09;临时去查了一下KNN和K-Means是啥&#xff0c;然后自己用C写了小例子&#xff0c;想着写都写了那就把代码贴出来吧。 顺便再聊聊自己对于这俩算法的理解。 下面是文心一言的回答…

十年诉讼,迈瑞真的赢了吗?

迁延十年&#xff0c;迈瑞与科曼的知识产权纠纷案究竟要如何解读&#xff1f; 发端于2013年&#xff0c;两家国内医疗器械行业知名公司间的专利互诉官司&#xff0c;成为全行业最具代表性的案例。但这一案例本质并不复杂&#xff1a;不过商业利益之争。 要在烈度不断抬升的市…

项目管理PMP6.0-五大过程组、十大知识领域、四十九个过程(记忆码:7664363734)

项目管理PMP6.0-五大过程组、十大知识领域、四十九个过程&#xff08;记忆码&#xff1a;7664363734&#xff09; 项目经理的影响力范围三者关系图&#xff08;五大过程组、十大知识领域、四十九个过程&#xff09;五大过程组十大知识领域十大知识领域之间联系 四十九个过程&am…

如何通过提升客户体验带来更大的增长、更好的客户留存率?

客户期望的转变 在一个日益数字化的世界里&#xff0c;有必要采取以客户为中心的思维方式。因为客户与企业互动的方式有很多是在数字空间发生的&#xff0c;客户的需求和模式已经转变。 这种情况已经酝酿了几年&#xff0c;但在2020年才打开闸门。随着疫情的爆发&#xff0c;企…

FTX的前世今生:崛起、辉煌与崩塌

FTX&#xff0c;一度被誉为加密货币领域的明星交易所&#xff0c;其快速的崛起和令人瞩目的崩塌吸引了全球的关注。让我们回顾一下FTX的前世今生&#xff0c;了解其短暂的辉煌和骤然的崩塌。 1. 崛起&#xff1a; FTX的创始人山姆班克曼-弗里德在加密货币领域具有深厚的背景和…

Linux主机间的相互免秘钥

主机间的相互免秘钥 1.生成密钥 ssh-keygen -t rsa -P -f ~/.ssh/id_rsa运行以上命令后会在 ~/.ssh/ 目录下生成一对密钥对。 2.拷贝公钥 把自己的公钥传递给对方主机即可&#xff0c;这个公钥文件必须放在对方主机的~/.ssh/authorized_keys 文件中。 ssh-copy-id -i ~/.s…

智能座舱架构与芯片 - (2) 架构篇

一、定义 1.1 智能座舱定义 按照百度百科的定义&#xff0c;智能座舱&#xff08;intelligent cabin&#xff09;旨在集成多种IT和人工智能技术&#xff0c;打造全新的车内一体化数字平台&#xff0c;为驾驶员提供智能体验&#xff0c;促进行车安全。目前国内外已经有很多研究…

Django ORM 执行复杂查询的技术与实践

概要 Django ORM&#xff08;Object-Relational Mapping&#xff09;是 Django 框架的核心组件之一&#xff0c;提供了一种高效、直观的方式来处理数据库操作。尽管简单查询在 Django ORM 中相对容易实现&#xff0c;但在面对复杂的数据请求时&#xff0c;需要更深入的了解和技…

【文末送书】深入浅出嵌入式虚拟机原理

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和技术。关…

「Verilog学习笔记」含有无关项的序列检测

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 timescale 1ns/1ns module sequence_detect(input clk,input rst_n,input a,output reg match);reg [8:0] a_tem ; always (posedge clk or negedge rst_n) begin if (~rs…

maven打包项目,然后给其他项目引用

A项目&#xff08;这个项目需要被打包&#xff0c;作为被引入的项目&#xff09;&#xff0c;不需要启动类&#xff0c;因为作为公共模块被B项目引入&#xff1a; package com.yunya.mvndependontest.rest;import org.springframework.web.bind.annotation.RequestMapping; im…

SpringDoc枚举字段处理与SpringBoot接收枚举参数处理

本期内容 添加SpringDoc配置展示枚举字段&#xff0c;在文档页面中显示枚举值和对应的描述添加SpringMVC配置使项目可以接收枚举值&#xff0c;根据枚举值找到对应的枚举 默认内容 先不做任何处理看一下直接使用枚举当做入参是什么效果。 定义一个枚举 package com.exampl…

0基础学习VR全景平台篇第122篇:VR视频剪辑和输出 - PR软件教程

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01; 开始之前如果没有接触过pr这款软件的话&#xff0c;建议先去看上一篇 认识视频剪辑软件Premiere 大致了解一下pr。 回到正题今天来教大家VR视频的剪辑和输出 我们先双击打开…

喜讯 | 聚铭下一代智慧安全运营中心入选2023年江苏省大数据产业发展试点示范项目

近日&#xff0c;江苏省工信厅公示2023年江苏省大数据产业发展试点示范项目名单。聚铭下一代智慧安全运营中心凭借扎实的技术实力和突出的产品优势成功入选。 为推动新兴数字产业集群建设&#xff0c;夯实大数据产业发展基础&#xff0c;提升产业供给能力和行业赋能效应&…

AD9361寄存器功能笔记之本振频率设定

LO的产生过程如图&#xff1a; 各个模块都有高灵活性。 1、参考时钟即是AD9361全局参考时钟&#xff0c;可以是外接晶振的片上DCXO&#xff0c;或是外部输入的有驱动能力的时钟信号。根据FM-COMMS5的设计&#xff0c;参考时钟可以使用时钟Buffer 40MHz晶振构成的参考频率源。 …