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区的数组。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python实现自动登录+获取数据

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 Dy这个东西想必大家都用过&#xff0c;而且还经常刷&#xff0c;今天就来用代码&#xff0c;获取它的视频数据 如果有什么疑惑/资料需要的可以点击文章末尾名片领取源码 环境使用 Python 3.8 Pycharm 模块使用 request…

时间序列中的6大类10种异常值处理方法(从根源上提高预测精度)

一、本文介绍 本文介绍的内容是在时间序列中异常值处理的方法&#xff0c;当我进行时间序列分析建模收集数据的过程中&#xff0c;往往都存在着一些特数据情况导致数据中存在着一些异常值&#xff0c;这些异常值往往会导致模型识别到不正常的模式从而无法准确的预测&#xff0…

每日一题(LeetCode)----数组--螺旋矩阵(一)

每日一题(LeetCode)----数组–螺旋矩阵&#xff08;一&#xff09; 1.题目&#xff08;54. 螺旋矩阵&#xff09; 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1…

Springboot+vue的社区医院管理系统(有报告),Javaee项目,springboot vue前后端分离项目

演示视频&#xff1a; Springbootvue的社区医院管理系统(有报告)&#xff0c;Javaee项目&#xff0c;springboot vue前后端分离项目 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的应急物资管理系统&#xff0c;采用M&#xff08;model&#xff09;V&am…

JavaApp自动化测试系列[v1.0.0][四种等待方式]

四种等待 隐式等待&#xff1a;是在尝试发现某个元素的时候&#xff0c;如果没能立刻发现&#xff0c;就等待固定长度的时间。默认设置是0秒。一旦设置了隐式等待时间&#xff0c;它的作用范围就是Webdriver对象实例的整个生命周期显示等待&#xff1a;定义了等待条件&#xf…

Python (十二) 文件

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一份大厂面试资料《史上最全大厂面试题》&#xff0c;Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等 …

chrome内置路径合集

设置黑夜模式&#xff1a; 输入网址&#xff1a;chrome://flags/ 搜索dark 改为enable 实验项目路径 chrome://flags/ 可用来启用或者关闭某些 Chrome 的实验功能 chrome://settings 将快速打开 Chrome 浏览器的设置页面&#xff0c;页面的内容分类划分为基础和高级设置选项 …

JOSEF 静态中间继电器 ZJY-420 DC220V 板前接线,带底座 增加触点

系列型号&#xff1a; ZJY-400中间继电器&#xff1b;ZJY-600中间继电器&#xff1b; ZJY-800中间继电器&#xff1b;ZJY-020中间继电器&#xff1b; ZJY-040中间继电器&#xff1b;ZJY-060中间继电器&#xff1b; ZJY-006中间继电器&#xff1b;ZJY-008中间继电器&#xff1b;…

GitHub 2023报告-开源和AI的现状

GitHub 2023报告-开源和AI的现状 深入探讨人工智能如何与开源互动&#xff0c;以及未来几年可能出现的趋势。 背景介绍 2023年&#xff0c;开源已成为全球软件开发的标准。无论是大公司还是小团队&#xff0c;都广泛使用开源技术进行项目开发。此外&#xff0c;随着机器学习和…

Notion AI会员订阅付费

一、Notion AI优势&#xff1a; 自动化任务&#xff1a;NotionAI可以自动完成一些重复性任务&#xff0c;例如对内容进行分类和标记&#xff0c;从而提高工作效率和减少人力成本。个性化建议&#xff1a;NotionAI可以根据用户的偏好和行为模式提供个性化的建议和推荐&#xff…

编译器优化代码研究

《Effective C》条款21&#xff1a; /** * 结论&#xff1a;对自定义类型对象表达式objA*objB objC; * 定义friend MyInt operator*(const MyInt& lhs,const MyInt& rhs) * 编译器优化后&#xff1a;operator*()函数内直接在调用接收处构造(此处的匿名临时对象)&am…

2023年以就业为目的学习Java还有必要吗?

文章目录 1活力四射的 Java2从零开始学会 Java3talk is cheap, show me the code4结语写作末尾 现在学 Java 找工作还有优势吗&#xff1f; 在某乎上可以看到大家对此问题的热议&#xff1a;“2023年以就业为目的学习Java还有必要吗&#xff1f;” 。有人说市场饱和&#xff0c…

VMware——WindowServer2012R2环境安装mysql5.7.14解压版_主从复制(图解版)

目录 一、服务器信息二、192.168.132.33主服务器上安装mysql&#xff08;主&#xff09;2.1、环境变量配置2.2、安装2.2.1、修改配置文件内容2.2.2、初始化mysql并指定超级用户密码2.2.3、安装mysql服务2.2.4、启动mysql服务2.2.5、登录用户管理及密码修改2.2.6、开启远程访问 …

HP惠普暗影精灵7Plus笔记本OMEN 17.3英寸游戏本17-ck0000恢复原厂Windows11预装OEM系统

链接&#xff1a;https://pan.baidu.com/s/1ukMXI2V3D0c-kVmIQSkbYQ?pwd2rbr 提取码&#xff1a;2rbr hp暗影7P原厂WIN11系统适用型号&#xff1a; 17-ck0056TX&#xff0c; 17-ck0055TX&#xff0c; 17-ck0054TX &#xff0c;17-ck0059TX 自带所有驱动、出厂时主题壁纸、…

数据湖的概念、发展背景和价值

数据湖是一个集中化的存储系统&#xff0c;旨在以低成本、大容量的方式&#xff0c;无需预先对数据进行结构化处理&#xff0c;存储各种结构化和非结构化数据。以下是数据湖概念、发展背景和价值的详细介绍。 数据湖概念 数据湖的概念源自于对传统数据仓库的补充。传统数据仓…

git常常用命令

这篇文章中&#xff0c;一些简单的&#xff0c;大家都知道的git 命令我就不再赘述&#xff0c;我只写出来最近在项目中常用到的一些命令。这些命令可以帮助我更好的开发。 git stash 请大家设想下面的场景&#xff0c;你的本地有两个分支&#xff0c;develop,fix分支&#xf…

java创建指定分辨率的图片或修改图片的分辨率(DPI)

因为java默认的图片像素分辨率DPI72&#xff0c;分辨率有点低。所以研究了一下如何创建指定DPI的方案。 DPI&#xff1a; 指的是每英尺的像素点(dots per inch) JPEG图片 JPEG图片的元数据定义参看oracle官网。 https://docs.oracle.com/javase/8/docs/api/javax/imageio/me…

关于“计算机中由于找不到msvcr120.dll,无法继续执行代码5种解决方法

今天&#xff0c;我想和大家分享一下关于“由于找不到msvcr120.dll,无法继续执行代码5种解决方法”的话题。在我们日常的使用中&#xff0c;有时候会遇到这样的问题&#xff1a;在运行某个程序时&#xff0c;突然提示“无法继续执行代码&#xff0c;因为找不到msvcr120.dll”。…

七天.NET 8操作SQLite入门到实战 - 第二天 在 Windows 上配置 SQLite环境

前言 SQLite的一个重要的特性是零配置的、无需服务器&#xff0c;这意味着不需要复杂的安装或管理。它跟微软的Access差不多&#xff0c;只是一个.db格式的文件。但是与Access不同的是&#xff0c;它不需要安装任何软件&#xff0c;非常轻巧。 七天.NET 8操作SQLite入门到实战…

Web功能测试有哪些常用方法?

检验方法 1页面链接检查每一个链接是否都有对应的页面&#xff0c;并且页面之间切换正确&#xff1b; 2相关性检查删除/增加一项会不会对其他项产生影响&#xff0c;如果产生影响&#xff0c;这些影响是否都正确。 3检查按钮的功能是否正确如update, cancel, delete, save等…