C语言算法(二分查找、文件读写)

news2024/9/19 10:15:48

二分查找

前提条件:数据有序,随机访问

#include <stdio.h>

int binary_search(int arr[],int n,int key);

int main(void) {}

int search(int arr[],int left,int right,int key) {
	//边界条件
	if(left > right) return -1;
	//int mid = (left + right) / 2;
	//防止溢出
	int mid = left + ((right - left) >> 1);
	if(key < arr[mid]) {
		return search(arr,left,mid - 1,key);
	}else fi(key > arr[mid]) {
		return search(arr,mid + 1,right,key);
	}else {
		return mid;
	}
}
//递归
int binary_search(int arr[],int n,int key) {
	return search(arr,0,n-1,key);
}
//循环
int binary_search(int arr[]],int n,int key) {
	if(n == 0) return -1;
	int left = 0,right = n-1;
	while(left <= right) {
		int mid = left + ((right - left) >> 1);
		if(key < arr[mid]) {
			right = mid - 1;
		}else if(key > arr[mid]) {
			left = mid + 1 ;
		}else {
			return mid;
		}
	}
	return -1;
}

二分查找的局限性
(1)二分查找依赖顺序表的结构,需要你有序性
(2)二分查找针对的是有序数据
(3)数据量太小没必要进行二分查找;
a)二分查可以减少比较操作;
b)比较操作很耗时
(4)数据量太大也不适合二分查找
(5)动态数据也不适合二分查找
(6)动态数据查找:平衡二叉树,哈希表

二分查找变种
(1)查找第一个与key值相同的元素
(2)查找最后一个与key值相同的元素
(3)查找最后一个小于等于key值的元素
(4)查找第一个大于等于key值的元素

//查找第一个与key值相同的元素
int binary_search1(int arr[],int n,int key) {
	int left = 0,right = n - 1;
	while(left <= right) {
		int mid = left + ((right-left) >> 1);
		if(key < arr[mid]) {
			right = mid - 1;
		}else if(key > arr[mid]) {
			left = mid + 1;
		}else {
			if(mid == left || arr[mid - 1] < key) {
				return mid;
			}
			right = mid - 1;
		}
	}
	return -1;
}
//查找最后一个与key值先沟通呢房的人元素
//查找最后一个小于等于key值的元素
int binary_search2(int arr[],int n,int key) {
	int left = 0,right = n - 1;
	while(left <= right) {
		int mid = left + ((right-left) >> 1);
		if(arr[mid] > key) {
			right = mid - 1;
		}else {
			if(mid == right || arr[mid + 1] > key) {
				return mid;
			}
			left  = mid +1;
		}
	}
	return -1;
}

文件

流:表示任意输入的源或输出的目的地
在这里插入图片描述

文件缓冲
缓冲区的分类:
满缓冲区:当缓冲区空的时候才会向缓冲区中写入数据,当缓冲区满的时候才会从缓冲区中读取数据
行缓冲区:每次从输入流中读取一行数据,每次也只会从缓冲区中被输出流读取一行数据
无缓冲区:不会进行缓冲,数据直接写到我们的目标文件内之中
在这里插入图片描述

刷新缓冲区
ffluh:刷新输出流中的数据到实际中的文件中去

标准流
在c语言中流对应的数据类型是—>FILE结构体
使用FILE*表示一个流
其中回从出流的起始位置,目前流读取到的位置

这三个标准流可以直接使用,使用完毕之后也不需要关闭
stdin:标准输入流,一般将其和键盘关联起来
stdout:标准输出流,一般将其和显示器关联起来
stderr:标准错误流,一般将其哦和显示器关联起来

文本文件和二进制文件
打开之后可以看得懂的就是文本文件,存储的是字符数据
打开之后看不懂的就是二进制文件,存储的是二进制形式数据

文本文件有两个特殊的性质:
(1)文本文件有行的概念,二进制文件没有行的概念【Linux中换行\n,windows中换行\r/\n
(2)文本文件可能包含一个特殊的文件末尾:EOF 【windows中表示文件末尾\x1a(使用快捷键ctrl + z可以向输入流中输入一个结尾字符)】

文本文件存储数据:优点:方便人类阅读和编辑;缺点:占用空间大
二进制文件存储数据:缺点:人类看不懂,不方便编辑;优点:占用空间小

打开文件和关闭文件
fopen打开文件
在这里插入图片描述

filename:文件路径
mode:打开文件的方式
文件路径分为绝对路径(从根目录,盘符开始,一致到文件所在的位置)和相对路径(从当前工作目录开始,一致到文件所在的位置)
打开方式:
r(rt)—>read只读,要求文件事先存在;
w(wt)—>write只写模式,不要求文件存在,如果文件存在,写之前会清空原文件内容;
a(at)—>append追加不要求文件存在,如果文件存在,不会清空源文件的内容
r+(rb+)—>可读可写,要求文件存在,如果写数据会清空数据
w+(wb+)—>可读可写,不要求文件存在
a+(ab+)—>可读可写,不要求文件存在,不会清空原有数据
以上方法用于读写文本文件,读写二进制文件为rb,wb,ab,rb+,wb+,ab+

fclose:关闭文件
在这里插入图片描述
如果成功关闭返回0;否则返回EOF

文件的读写
文本文件的读写
fgetc:一次读一个字符, 可以从任意输入流中读数据
fputc:一次写一个字符,可以将数据写到任意的输出流中
fgets:一次读取一行,读到换行符为止,可以从任意的流中读取字符串
fputs:把一个字符串写入到一个输出流中
fscanf:用格式化的方式将数据从标准输入流stdin中读入
fprintf:用格式化的方式将数据写到stdout标准输出流中

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
从stream流中读取最多count个数据到str中,遇到换行符就停止读入,会将存储数据的st指针返回回来,如果失败会返回空指针

在这里插入图片描述
将str字符串写出到输出流stream中

#define _CRT_SECURE_NO_WARINGS
#include <stdio.h>
#include <stdlib.h>
#define N 100
int main(int argc,char *argv[]) {
	if(argc != 3) {
		fprintf(stderr,"Invalid arguments.\n");//向stderr错误输出流中输入错误信息
		exit(1);
	}
	FILE* src = fopen(argv[1],"r");//打开文件
	if(src == NULL) {
		printf("Error:open %s failed.\n",argv[1]);
		exit(1);
	}
	FILE* dest = fopen(argv[2],"w");
	if(dest == NULL) {
		printf("Error:open %s failed.\n",argv[2]);
		fclose(src);
		exit(1);
	}
	//读写数据
	//每次读取字符
	//int ch;
	//while((ch = fgetc(src) != EOF)) {
	//	fputc(ch,dest);//将字符写入dest流中
	//}
	//读写一行数据
	char buf[N];
	while(fgets(buf,N,src) != NULL) {
		fputs(buf,dest);
	}
	//关闭流
	fclose(src);
	fclose(dest);
	
	return 0;
}
#include <stdio.h>

typedef struct student_s{
	int number;
	char name[25];
	int chinese;
	int math;
	int english;
}Student;

int main(void) {
	//序列化:把内存中的对象持久化(格式:文本格式)xml,json存在磁盘中
	Student s = {1,"xixi",100,100,100};
	
	FILE* fp = fopen("student.dat","w");
	if(fp == NULL) {
		fprintf(stderr,"Error:open student.dat failed.\n");
		exit(1);
	}
	fprintf(fp,"%d %s %d %d %d\n",s.number,s.name,s.chinese,s.math,s.english);
	fclose(fp);
	//反序列化:把持久化的数据加载到内存,斌生产对应的对象
	FILE* fp = fopen("student.dat","r");
	if(fp == NULL) {
		fprintf(stderr,"Error:open student.dat failed.\n");
		exit(1);
	}
	Student s;
	fscanf(fp,"%d%s%d%d%D",&s.number,&s.name,&s.chinese,&s.math,&s.english);
	fclose(fp);
	return 0;	
}

二进制文件的读写

在这里插入图片描述

buffer:把文件中的数据读到buffer中
size:每个元素的大小
count:表示又多少个元素
stream:需要从那个数据流中读取数据
返回值是成功读入数据的个数

在这里插入图片描述

buffer:内存中的对象,我们要将内存buffer中的数据写入到文件中
size:每个对象的大小
count:要写的对象的数量
stream:要写到的目标输出流
返回值是成功写出对象的个数, 一般情况下返回值和count值是相同的

#define _CRT_SECURE_NO_WARINGS
#include <stdio.h>
#include <stdlib.h>
#define N 4096
int main(int argc,char *argv[]) {
	if(argc != 3) {
		fprintf(stderr,"Invalid arguments.\n");//向stderr错误输出流中输入错误信息
		exit(1);
	}
	FILE* src = fopen(argv[1],"rb");//打开文件
	if(src == NULL) {
		printf("Error:open %s failed.\n",argv[1]);
		exit(1);
	}
	FILE* dest = fopen(argv[2],"wb");
	if(dest == NULL) {
		printf("Error:open %s failed.\n",argv[2]);
		fclose(src);
		exit(1);
	}
	//读写数据
	char buf[4096]; 
	int n;//读入数据的个数
	while((n = fread(buf, 1, N, src)) != 0) {//从src中的数据读入到buf中
	fwrite(buf, 1, n, dest);//将src中的数据写入到dest中去
		
	}
	//关闭流
	fclose(src);
	fclose(dest);
	
	return 0;
}
//二进制形式序列化
#include <stdio.h>

typedef struct student_s{
	int number;
	char name[25];
	int chinese;
	int math;
	int english;
}Student;

int main(void) {
	//序列化:把内存中的对象持久化(格式:文本格式)xml,json存在磁盘中
	Student s = {1,"xixi",100,100,100};
	
	FILE* fp = fopen("student.dat","wb");
	if(fp == NULL) {
		fprintf(stderr,"Error:open student.dat failed.\n");
		exit(1);
	}
	fwrite(&s,sizeof(s),1,fp);
	fclose(fp);
	
	//反序列化:把持久化的数据加载到内存,斌生产对应的对象
	FILE* fp = fopen("student.dat","rb");
	if(fp == NULL) {
		fprintf(stderr,"Error:open student.dat failed.\n");
		exit(1);
	}
	Student s;
	fread(&s,sizeof(s),1,fp);
	fclose(fp);
	return 0;	
}

文件定位

查找文件中对应的位置,可以改变读写指针位置
int fseek(FILE* stream,long int offset,int whence)
offset:以字节为单位计算偏移量
whence:参照点【whence取值:(1)SEEK_SET:文件的起始位置;(2)SEEK_CUR:文件的当前位置;(3)SEEK_END:文件的末尾位置】
移动到文件的开始:fseek(stream,0L,SEEK_SET);<==>rewind(stream);
往回移动10个字节:fseek(stream,-10L,SEEK_CUR);
移动到文件的末尾:fseek(stream,0L,SEEK_END);
打印当前文件的位置(相对于SEEK_SET而言)
long ftell(FILE* stream)
可以将处于任意读写位置的指针指向开始位置
void rewind(FILE* stream)

#include <stdio.h>

typedef struct student_s{
	int number;
	char name[25];
	int chinese;
	int math;
	int english;
}Student;

int main(void) {
	//序列化:把内存中的对象持久化(格式:文本格式)xml,json存在磁盘中
	Student s = {1,"xixi",100,100,100};
	
	FILE* fp = fopen("student.dat","wb+");
	if(fp == NULL) {
		fprintf(stderr,"Error:open student.dat failed.\n");
		exit(1);
	}
	fwrite(&s,sizeof(s),1,fp);
	
	//反序列化:把持久化的数据加载到内存,斌生产对应的对象
	Student s1;
	rewind(fp);//重定向文件位置 <==>fseek(fp,0L,SEEK_SET)
	fread(&s1,sizeof(s1),1,fp);
	fclose(fp);
	return 0;	
}

错误处理
在这里插入图片描述
如果数值计算、文件读写发生错误,系统调用(sysytem call)会把errno设置为对应的值

#include <stdio.h>
#include <errno.h>
#inlcude <math.h>

int main(void) {
	printf("%d\n",errno);//0
	printf("%s\n",strerror(errno));//No error
	perror("Error");// Error:No error
	log(0,0);
	printf("%d\n",errno);//34
	printf("%s\n",strerror(errno));// Result too large
	perror("Error");//Error: Result too large
	//虽然errnno可以告诉我们发生错误的系统的调用返回的值,但是我们很难去确定齐放回的数值表示什么含义我们可以使用strerror(errno)打印其字符串表达
	
	return 0;
}

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

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

相关文章

MidTool的AIGC与NFT的结合-艺术创作和版权保护的革新

在数字艺术和区块链技术的交汇点上&#xff0c;NFT&#xff08;非同质化代币&#xff09;正以其独特的方式重塑艺术品的收藏与交易。将MidTool&#xff08;https://www.aimidtool.com/&#xff09;的AIGC&#xff08;人工智能生成内容&#xff09;创作的图片转为NFT&#xff0c…

数据库基础知识1

目录 数据库的使用 登录mysql 命令语法 常用命令 ​编辑 navicat建立连接 mysql授权管理命令 ​编辑mysql权限 数据导入导出 实例 数据导出 未登录 已经登录 导出导入的代码对比 ​编辑 导入导出的一个坑 python的导入导出 数据库基础知识 特点 需要掌握的程…

嵌入式——循环队列

循环队列 (Circular Queue) 是一种数据结构(或称环形队列、圆形队列)。它类似于普通队列,但是在循环队列中,当队列尾部到达数组的末尾时,它会从数组的开头重新开始。这种数据结构通常用于需要固定大小的队列,例如计算机内存中的缓冲区。循环队列可以通过数组或链表实现,…

使用Docker-compose快速构建Nacos服务

在微服务架构中&#xff0c;服务的注册与发现扮演着至关重要的角色。Nacos&#xff08;Naming and Configuration Service&#xff09;是阿里巴巴开源的服务注册与发现组件&#xff0c;致力于支持动态配置管理和服务发现。最近&#xff0c;一位朋友表达了对搭建一套Nacos开发环…

速卖通店铺销量飙升:掌握自养号测评(补单),轻松提升销售量

很多卖家在经营速卖通店铺时&#xff0c;都希望能提高自己店铺的曝光率。但对于一些新手卖家来说&#xff0c;可能不太清楚曝光率的具体含义以及如何提升。那么&#xff0c;让我们一起来探讨一下这个问题。 曝光率&#xff0c;简而言之&#xff0c;是指您的店铺和产品展示给顾…

springboot git配置文件自动刷新失败问题排查

http://{ip}:{port}/refresh 说明&#xff1a;springBoot版本是1.5.9&#xff0c;接口路径与2.x&#xff0c;不同 路径区别&#xff1a;/refresh VS /actuator/refresh 用postman调用refresh接口刷新git配置&#xff0c;报错如下&#xff0c;没有权限 在服务本地启动&#…

【Java】2023年业务实践中遇到的所有OOM情况及实战总结

OOM分析&实战 引言&#xff1a;一、JVM内存结构二、JVM OOM错误情况三、实践案例一案例二案例三 四、总结五、分析工具推荐六、参考文献 引言&#xff1a; 在Java开发中&#xff0c;随着应用程序变得越来越复杂&#xff0c;内存管理问题也变得愈加重要。而在JVM中的"O…

笔试案例2

文章目录 1、笔试案例22、思维导图 1、笔试案例2 09&#xff09;查询学过「张三」老师授课的同学的信息 selects.*,c.cname,t.tname,sc.score from t_mysql_teacher t, t_mysql_course c, t_mysql_student s, t_mysql_score sc where t.tidc.cid and c.cidsc.cid and sc.sids…

数据结构-测试6

一、判断题 1.若一个栈的输入序列为{1, 2, 3, 4, 5}&#xff0c;则不可能得到{3, 4, 1, 2, 5}这样的出栈序列。&#xff08;T&#xff09; 3比4先进&#xff0c;所以3比4后出&#xff0c;所以不可能得到 2. 在二叉排序树中&#xff0c;每个结点的关键字都比左孩子关键字大&…

【Qt开发】PyQt6--标签控件

标签控件 Qlabel设置标签文本文本的对齐方式为标签设置超链接为标签设置图片获取标签文本 Qlabel QLabel标签控件&#xff0c;用于显示用户不能编辑的文本&#xff0c;主要起提示的作用 设置标签文本 文本的对齐方式 通过这可以设置文本对齐方式 为标签设置超链接 勾选以上…

NGS基因测序(panel)报告解读数据库汇总

今天我们来梳理一下肿瘤基因报告解读常见的数据库&#xff0c;大家有机会可以自己查询并且解读&#xff0c;涉及到的数据库有dbSNP数据库 、gnomAD数据库、ExAC数据库、1000 Genomes、HGMD 数据库、OMIM数据库、ClinVar数据库、InterVar数据库 、ClinGen数据库、GeneReviews数据…

大创项目推荐 深度学习图像风格迁移

文章目录 0 前言1 VGG网络2 风格迁移3 内容损失4 风格损失5 主代码实现6 迁移模型实现7 效果展示8 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习图像风格迁移 - opencv python 该项目较为新颖&#xff0c;适合作为竞赛课题…

自学编程资源收集

Java&#xff0c;Python&#xff0c;C&#xff0c;JavaScript,SpringBoot&#xff0c;Vue,MySql等各种编程资料收集 mksz712-系统玩转OpenGLAI&#xff0c;实现各种酷炫视频特效mksz709-从0到1训练私有大模型 &#xff0c;企业急迫需求&#xff0c;抢占市场先机~8mksz702-Chat…

布偶猫必囤主食冻干有哪些?三款K9、sc、希喂主食冻干深度测评!

喂养布偶猫的小诀窍&#xff1a;既要满足其食肉习性&#xff0c;又需关注其敏感肠胃。主食冻干是理想选择&#xff0c;它既符合猫咪天然的饮食结构&#xff0c;又采用新鲜生肉为原料。搭配其他营养元素&#xff0c;既美味又营养&#xff0c;还能增强抵抗力。我们将为您测评市场…

IPv6路由协议---IPv6动态路由(RIPng)

IPv6动态路由协议 动态路由协议有自己的路由算法,能够自动适应网络拓扑的变化,适用于具有一定数量三层设备的网络。缺点是配置对用户要求比较高,对系统的要求高于静态路由,并将占用一定的网络资源和系统资源。 路由表和FIB表 路由器转发数据包的关键是路由表和FIB表,每…

如何写一篇专利?格式与要求

如何写一篇专利&#xff1f;格式与要求 知识产权专利类型发明实用新型外观设计 专利的审查专利授权的标准新颖性创造性实用性 不授予专利的情形 专利的挖掘专利五书权力要求书说明书技术领域背景技术发明内容附图说明具体实施方式 说明书附图说明书摘要摘要附图 知识产权 市场…

流量控制在计算机网络中的应用

计算机网络是我们现代社会中必不可少的一部分&#xff0c;其在信息传输和分享方面起到了至关重要的作用。然而&#xff0c;面对大量的数据流量和用户请求&#xff0c;网络必须进行流量控制&#xff0c;以保证网络的稳定性和性能。本文将探讨流量控制在计算机网络中的应用。 流…

本地部署Canal笔记-实现MySQL与ElasticSearch7数据同步

背景 本地搭建canal实现mysql数据到es的简单的数据同步&#xff0c;仅供学习参考 建议首先熟悉一下canal同步方式&#xff1a;https://github.com/alibaba/canal/wiki 前提条件 本地搭建MySQL数据库本地搭建ElasticSearch本地搭建canal-server本地搭建canal-adapter 操作步骤…

设计模式④ :分开考虑

一、前言 有时候不想动脑子&#xff0c;就懒得看源码又不像浪费时间所以会看看书&#xff0c;但是又记不住&#xff0c;所以决定开始写"抄书"系列。本系列大部分内容都是来源于《 图解设计模式》&#xff08;【日】结城浩 著&#xff09;。该系列文章可随意转载。 …

小白入门基础 - Restful

一&#xff1a;REST与RESTful&#xff1a; REST&#xff1a;表现层状态转移&#xff0c;资源在网络中以某种形式进行状态转移。 RESTful是基于REST理念的一套开发风格&#xff0c;是具体的开发规则。 服务器端只返回数据&#xff0c;以json或者xml的格式。 RESTful开发规范&a…