7.数组(一维数组、二维数组、C99中的变长数组、二分查找法)

news2025/1/19 17:16:36

数组

    • 1.数组的概念
    • 2.一维数组
      • 2.1 一维数组的创建
      • 2.2 一维数组的类型
      • 2.3 一维数组的初始化
      • 2.4 一维数组的下标
      • 2.5 一维数组的输入与输出
      • 2.6 一维数组在内存中的存储
      • 2.7 利用sizeof()计算数组元素的个数
    • 3.二维数组
      • 3.1 二维数组的概念
      • 3.2 二维数组的创建
      • 3.3 二维数组的初始化
      • 3.4 二维数组的下标
      • 3.5 二维数组的输入与输出
      • 3.6 二维数组在内存中的存储
    • 3.C99中的变长数组
    • 4.二分查找法(也称折半查找法)

1.数组的概念

数组是一组相同类型元素的集合,其特点有
1.数组存放的是1个或者多个数据,但是数组元素个数不能为0
2.数组中存放的多个数据,类型是相同的
数组分为一维数组和多维数组,多为数组一般以二维数组为主。

2.一维数组

2.1 一维数组的创建

格式:数据类型 数组名[常量值];
例 int num[10];

2.2 一维数组的类型

去掉数组名剩下的就是数组类型,例 int num[10]; 其数组类型为int [10]
数组元素的数据类型 可以是char、int、float等 数组内的元素数据类型都相同

2.3 一维数组的初始化

//完全初始化
int num[5] = {1,2,3,4,5};

//不完全初始化,除了1 2 3,剩下的其余元素都默认为0
int num[5] = {1,2,3};

//初始化1 2 3,长度也为3
int num[] = {1,2,3};

2.4 一维数组的下标

在C语⾔中数组的访问提供了⼀个操作符[ ] ,这个操作符叫:下标引用操作符
注意区分 定义数组时 和 调用数组元素时 [ ] 内常量的区别
定义时里面的常量表示元素的个数
调用时里面的常量表示数组下标,也就是索引位
数组下标是从0开始数起的
在这里插入图片描述

举例:

//注意区分 定义数组时 和 访问数组元素时 []的区别
int num[5] = {1,2,3,4,5};//这里num[5]表示的是数组长度为5
printf("数组下标为4的值:%d", num[4]);//这里num[4]表示的是访问数组下标为4的数组元素

输出结果
在这里插入图片描述

2.5 一维数组的输入与输出

输出

//输出
int main() {
	int arr[9] = {1,2,3,4,5,6,7,8,9};
	for (int i = 0; i < 9; i++)//这里小于9是因为长度为9的数组 下标范围为0~8
	{
		printf("arr[%d] = %d\n",i,arr[i]);
	}
	return 0;
}

输出结果
在这里插入图片描述


输入

//输入
int main() {
	int arr[9];
	for (int i = 0; i < 9; i++)
	{
		scanf("%d",&arr[i]);
	}

	for (int i = 0; i < 9; i++)//这里小于9是因为长度为9的数组 下标范围为0~8
	{
		printf("arr[%d] = %d\n",i,arr[i]);
	}
	return 0;
}

输入结果
在这里插入图片描述

2.6 一维数组在内存中的存储

一维数组在内存中的存储地址,随着下标增长,由小变大
数组在内存中是连续存放的,以整型数组为例,每两个相邻的数组元素之间相差4(因为一个整型是4个字节)

int main() {
	int arr[9] = {1,2,3,4,5,6,7,8,9};
	for (int i = 0; i < 9; i++)
	{
		printf("arr[%d] = %p\n",i,&arr[i]);
	}
	return 0;
}

输出结果(32位(x86)环境下)
在这里插入图片描述

16进制的形式表示内存中存储的地址,每个数据元素之间都差4,因为是int类型的数据元素

2.7 利用sizeof()计算数组元素的个数

sizeof()函数是C语言中的一个关键字
作用:计算类型或者变量的大小
单位是字节(byte)

因为数组中的所有元素的数据类型都是相同的,所以每个数据元素的大小相同
即:所占内存空间总大小 / 对应数组元素的数据类型 = 数组内元素的个数

int main() {
	int arr[10] = {0};//这里我们就非完全初始化数组,所以我们不知道数组有多少个元素个数
	printf("数组 int arr[10] 所占内存空间的总大小:%zd 字节\n",sizeof(arr));
	printf("数组 int arr[10] 其中一个数组元素所占内存空间的大小:%zd 字节\n",sizeof(arr[0]));
	
	//所占内存空间总大小 / 对应数组元素的数据类型 = 数组内元素的个数
	int sum = sizeof(arr) / sizeof(arr[0]);
	printf("数组中元素的个数:%d", sum);

	return 0;
}

输出结果
在这里插入图片描述

3.二维数组

3.1 二维数组的概念

二维数组:相当于把一维数组做为数组元素,此时就是二维数组
依此类推,三维数组就是二维数组被做为数组元素的数组
二维数组以上的数组都统称为多维数组

3.2 二维数组的创建

格式:数据类型 数组名[常量值1][常量值2];
例:
int num[10][10];
第一个10表示 数组有10行
第二个10表示 每一行有10个数组元素

3.3 二维数组的初始化

// 不完全初始化
int arr1[3][3] = {1,2,3};
int arr2[3][3] = {0};

// 完全初始化
int arr3[3][3] = {1,2,3, 4,5,6, 7,8,9};

//按照行初始化
int arr4[3][3] = {{1,2,3},{4,5,6},{7,8,9}};

//初始化时可以省略行,但是不能省略列
int arr5[][3] = { 1,2 };
int arr6[][3] = { 1,2,3,4,5};
int arr7[][3] = { {1,2},{4,5},{7,8} };

3.4 二维数组的下标

二维数组中行的下标从0开始,列的坐标也是从0开始
初始化时可以省略行,但是不能省略列
int man[可以省略][不能省略];

3.5 二维数组的输入与输出

输入

	//输入
	for (int i = 0; i < 3; i++)//行号
	{
		for (int j = 0; j < 3; j++)//列号
		{
			scanf("%d ", &arr[i][j]);//记得加&
		}
	}

输出

	//输出
	for (int i = 0; i < 3; i++)//行号
	{
		for (int j = 0; j < 3; j++)//列号
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}

3.6 二维数组在内存中的存储

二维数组每一行内部的每个元素都是相邻的
以整型为例
每两个相邻的数组元素之间相差4个字节(因为一个整型是4个字节)
跨行连接处的每个元素也都是只差4个字节,所以二维数组在内存中也是连续存放的

int main() {
	int arr[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
	for (int i = 0; i < 3; i++)//行号
	{
		for (int j = 0; j < 3; j++)//列号
		{
			printf("arr[%d][%d] = %p\n", i, j, &arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

输出结果
在这里插入图片描述

3.C99中的变长数组

在C99标准之前,C语言在创建数组的时候,数组大小必须得用常量或常量表达式来表示,或者初始化数组的时候省略数组大小,直接自己输入数组元素。

1.用常量来表示数组大小
int arr[5];
2.省略数组大小,开始直接自己输入元素
int arr[] = {1,2,3,4,5};

这样创建数组会带来非常大的限制,就是数组的大小无法灵活的变化,必须在开始的时候就写死数组的大小。

所有在C99中给定了一个变长数组(variable-length array,简称VLA) 的新特性,允许我们可以使用变量来创建数组大小。

//这样一来就可以根据输入的值来创建对应的大小的数组了
int n;
scanf("%d",&n)
int arr[n];

上述例子中arr为边长数组,它的数组大小取决于输入值n的大小,编译器无法提前确定数组大小,只有程序运行时,才能知道n是多少。(即变长数组的大小只有在运行时才能确定,所以变长数组也就不能初始化
好处:在开发程序时,不需要特地的去考虑定义数组的大小范围等,程序在运行时可以精确的根据对变量的赋值来分配数组的大小。
注意:程序运行时,根据变量的大小来分配数组的大小,数组的大小一旦被分配,就确定不再变化。(可变是指创建数组时的变量可变,不需要唯一固定值;而不是说能随意的改变数组的大小)


可惜的是在VS2022上支持大部分C99语法,但是VS中不支持C99中的变长数组

#include <stdio.h>
int main(){
	int n = 0;
	scanf("%d", &n);//根据输⼊数值确定数组的⼤⼩
	int arr[n];
	int i = 0;
	for (i = 0; i < n; i++){
		scanf("%d", &arr[i]);
	}
	for (i = 0; i < n; i++){
		printf("%d ", arr[i]);
	}
return 0;
}

输入:
5
1 2 3 4 5

输出:
1 2 3 4 5

4.二分查找法(也称折半查找法)

拿传统的查找方法来作比较

就是从数组下标0的元素开始,逐次递增,来和要查找的数进行比较
缺点:如果要查找的数很大,上万上千,那么也要查找上万上千次;查找的数越大查找起来越费劲

//传统查找方式(麻烦,什么年代了还在用传统香。。。方法)
int main() {
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 0;//要查找的数
	int count = 1;//查找次数
	scanf("%d", &k);
	
	int sz = sizeof(arr) / sizeof(arr[0]);//数组内元素个数

	int find = 0;//假设找不到

	int i = 0;
	//循环递增数组下标作比较
	for (i = 0; i < sz; i++)
	{
		if (k == arr[i]) {
			printf("成功找到arr[%d]=%d,共查找了%d次", i,arr[i],count);
			find = 1;
			break;
		}
		count++;
	}
	if (find == 0)
	{
		printf("查找了%d次,找不到",count);
	}
	return 0;
}

在这里插入图片描述


二分查找法

开始:
将列表的起始索引 low 设置为 0
将列表的结束索引 high 设置为数组长度减1

循环条件为(low 小于等于 high):
    将中间索引 mid 设置为 (low + high) 的一半
    
   如果列表的mid下标对应的元素小于目标值:
        将 low 设置为 mid 加 1
   如果列表的mid下标对应的元素大于目标值:
        将 high 设置为 mid 减 1
   否则(也就是low 等于 high 时):
   		mid 下标对应的元素 等于 目标值
   		退出循环
//二分查找
int main() {
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 0;//要查找的数
	scanf("%d", &k);
	int count = 1;//查找次数
	int find = 0;//假设找不到

	int sz = sizeof(arr) / sizeof(arr[0]);//数组内元素个数(组数长度)

	//low和high都是指下标位置
	int low = 0;
	int high = sz - 1;

	while (low <= high)
	{
		int mid = (low + high) / 2;

		//以下方法为 int mid = low + high 的优化方法:
		//之所以这么写是为了防止数据类型超出上限
		//int mid = low + (high - low)/2;

		if (arr[mid] < k)
		{
			low = mid + 1;
			count++;
		}
		else if (arr[mid] > k) {
			high = mid - 1;
			count++;
		}
		else
		{
			printf("成功找到arr[%d]=%d,共查找了%d次", mid, arr[mid], count);
			find = 1;
			break;
		}
	}
	if (find == 0)
	{
		printf("找不到");
	}
	return 0;
}

在这里插入图片描述

以int arr[] = { 1,2,3,4,5,6,7,8,9,10 };为例
虽然说传统查找方法6次 二分查找法3次差别不是特别大
但是随着数组的大小变大,二分查找的效率优势会越来越明显

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

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

相关文章

探索 GPTCache|GPT-4 将开启多模态 AI 时代,GPTCache + Milvus 带来省钱秘籍

世界正处于数字化的浪潮中&#xff0c;为了更好理解和分析大量数据&#xff0c;人们对于人工智能&#xff08;AI&#xff09;解决方案的需求呈爆炸式增长。 此前&#xff0c;OpenAI 推出基于 GPT-3.5 模型的智能对话机器人 ChatGPT&#xff0c;在自然语言处理&#xff08;NLP&a…

深度学习论文: Towards Total Recall in Industrial Anomaly Detection及其PyTorch实现

深度学习论文: Towards Total Recall in Industrial Anomaly Detection及其PyTorch实现 Towards Total Recall in Industrial Anomaly Detection PDF: https://arxiv.org/pdf/2106.08265.pdf PyTorch代码: https://github.com/shanglianlm0525/CvPytorch PyTorch代码: https://…

burp suite 2023版 模块详解《一》

burp suite2023版 模块详解<一> Brup suite 仪表盘、目标、代理模块详解 dashboard&#xff08;仪表盘&#xff09;&#xff1a; Burp Suite的dashboard是一个总览视图&#xff0c;显示有关目标和代理的重要信息。我们可以在仪表板上查看最近操作的概要、目标的状态和代…

vue 新学习 04 css样式绑定,渲染,key的重要意义

之前的html文件如何去绑定css样式&#xff1f; 01.首先在html文件中&#xff0c;在<head>标签中&#xff0c;用<style>中去写样式&#xff0c;通过html标签(每一个标签都有这样子的属性)中的class或者是id属性来完成<style>中的描绘的样式的用。 例子&#x…

用blender做一层石墨烯

文章目录 1 创建正六边形2 复制正六边形3 阵列4 球棍模型 1 创建正六边形 ShiftA->网格->圆环->左下角出现添加圆环菜单&#xff0c;将顶点设为6&#xff0c;得到一个正六边形。按下tab键进入编辑模式->快捷键F填充&#xff0c;得到下图 2 复制正六边形 首先将轴…

路由器工作原理(第二十九课)

路由器工作原理(第二十九课) 一图胜过千言 1) 路由:数据从一个网络到另外一个网络之间转发数据包的过程称为路由 2) 路由器:连接不同网络,实现不同网段之间的通信 3)路由表:路由器选择数据的传输路径的依据 原始的路由表 Destination/Mask Proto Pre Cost …

服务器数据恢复-raid5同步过程中又有一块磁盘报警的数据恢复案例

服务器数据恢复环境&#xff1a; 某研究院一台DELL存储&#xff0c;15块硬盘搭建的一组RAID5磁盘阵列。 该RAID5阵列只有一个卷组&#xff0c;该卷组占用了阵列的全部空间&#xff1b;该卷组只有一个起始位置为0扇区的XFS裸分区。 服务器故障&初检&分析&#xff1a; 该…

大数据课程E8——Flume的Ganglia

文章作者邮箱&#xff1a;yugongshiyesina.cn 地址&#xff1a;广东惠州 ▲ 本章节目的 ⚪ 了解Ganglia的概念&#xff1b; ⚪ 掌握Ganglia的安装操作&#xff1b; ⚪ 掌握Ganglia的监控Flume操作&#xff1b; 一、概述 1. Ganglia是UC Berkeley发起的一个开源…

LwIP以太网在初始化过程中卡死整个程序的问题排查解决

LwIP以太网在初始化过程中卡死整个程序 问题描述 当有以太网初始化的时候整个程序就有可能卡死&#xff0c;去掉以太网初始化整个程序没有卡死 以太网PHY初始化过程会有自协商过程&#xff0c;时间比较长&#xff0c;所以创建一个线程在线程中初始化。 有时候LwIP初始化不会…

【LeetCode】226.翻转二叉树

题目 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]示例 2&#xff1a; 输入&#xff1a;root [2,1,3] 输出&#xff1a;[2,3,1]示例 3…

qq录屏怎么操作?还有什么好用的录屏方法?

在现在这个信息时代&#xff0c;我们经常需要用到录屏这个功能。比如&#xff0c;我们需要制作教学视频、演示文稿或其他一些需要展示屏幕操作的场合。那么&#xff0c;QQ录屏是一个不错的选择&#xff0c;它可以帮助我们轻松地完成这些任务。 QQ录屏的操作方法 首先&#xff…

C++如何用OpenCV中实现图像的边缘检测和轮廓提取?

最近有个项目需要做细孔定位和孔距测量&#xff0c;需要做边缘检测和轮廓提取&#xff0c;先看初步效果图&#xff1a; 主要实现代码&#xff1a; int MainWindow::Test() {// 2.9 单个像素长度um 5倍double dbUnit 2.9/(1000*5);// 定义显示窗口namedWindow("src"…

控件旋转90度,并跟随大小缩放

控件旋转角度&#xff0c;并跟随缩放改变大小 背景使用控件结果 背景 一个项目需求&#xff0c;需要旋转某个控件90使用&#xff0c;在网上找了很多资料&#xff0c;没有特别合适的&#xff0c;自己试水试了一天半&#xff0c;终于弄了个大概其&#xff0c;特此记录 使用控件…

机器学习笔记之优化算法(七)线搜索方法(步长角度;非精确搜索;Wolfe Condition)

机器学习笔记之优化算法——线搜索方法[步长角度&#xff0c;非精确搜索&#xff0c;Wolfe Condition] 引言回顾&#xff1a; Armijo \text{Armijo} Armijo准则及其弊端 Glodstein \text{Glodstein} Glodstein准则及其弊端 Wolfe Condition \text{Wolfe Condition} Wolfe Condi…

CDH基于Kerberos开启身份验证实践总结

CDH基于Kerberos开启身份验证实践总结 前言简介Kerberos是什么Kerberos解决什么问题 Kerberos基本概念Kerberos认证流程Kerberos基本配置principalkeytabkrb5.confkdc.confkadm5.aclkerberos数据库 访问示例数据库访问信息 其他kerberos常用命令[Git Bash支持make命令](https:/…

在线餐饮油烟实时监测系统的设计与实现

安科瑞 华楠 摘 要&#xff1a;为了解决传统油烟检测方法中成本高、效率低、实时性差等问题&#xff0c;设计开发了一种在线油烟实时监测系统&#xff1b;系统由采集、通讯、服务器和用户交互四个模块组成&#xff1b;采集模块采集油烟数据&#xff0c;通过GPRS通讯技术将数据发…

13.元素尺寸与位置

原理&#xff1a;通过js的方式&#xff0c;得到元素在页面中的位置 13.1 元素尺寸与位置-尺寸 1.获取宽高: ●获取元素的自身宽高、包含元素自身设置的宽高、padding、border ● offsetWidth和offsetHeight ●获取出来的是数值&#xff0c;方便计算 ●注意&#xff1a;获取的…

基于DCT变换和huffman编码的语音压缩算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 多通道滤波 4.2 DCT变换 4.3 量化 4.3 哈夫曼编码 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ................................…

HTTP杂谈之Referer和Origin请求头再探

一 关于Referer和Origin的汇总 1) 知识是凌乱的,各位看官看个热闹即可2) 内容不断更新1、理解有盲区,需要及时纠正2、内容交叉有重复,需要适当删减3、扩展视野3) 以下内容都与Referer和Origin请求头有关联 nginx防盗链 HTTP杂谈之Referrer-Policy响应头 iframe标签referre…

go练习 day01

DTO: note_dto.go package dtoimport "king/model"type NoteAddDTO struct {ID uintTitle string json:"title" form:"title" binding:"required" message:"标题不能为空"Content string json:"conten…