第六章、数组

本文详细介绍了数组的概念、不同类型数组的创建、初始化方法,以及内存布局。重点讲解了一维数组、二维数组的初始化,包括完全和不完全初始化,并探讨了数组元素的地址计算和内存连续性。此外,还涉及了数组的排序(如二分查找)和变长数组的特点。
摘要由CSDN通过智能技术生成

数组是一组相同类型元素的集合

1、数组中存放的是1个或者多个数据,但是数组元素个数不能为0

2、数组中存放的多个数据类型是相同的

数组的分类

一维数组、二维数组、多维数组

创建数组的基本语法格式:

type arr_name[常量值];

存放在数组的值被称为数组的元素,数组在创建的时候可以指定数组的大小和数组的元素类型。

type:可以是int,short,float,char等。

arr_name:是数组名,起有意义的。

[]中的常量值用来指定数组的大小。

一维数组的初始化

1、完全初始化

#include<stdio.h>
int main(void)
{
	int data[10] = { 0,1,2,3,4,5,6,7,8,9 };		//完全初始化
	return 0;
}

2、不完全初始化

剩余元素默认初始化为0

#include<stdio.h>
int main(void)
{
	int data[10] = { 0,1,2,3,4,5};		//不完全初始化
	return 0;
}

3、数组如果初始化了,也可以省略数组的大小指定

#include<stdio.h>
int main(void)
{
	int data[] = { 0,1,2,3,4,5};    //可以不指定数组的大小
	return 0;
}

数组也是有类型的,数组算是一种自定义的类型,去掉数组名留下的就是数组的类型

#include<stdio.h>
int main(void)
{
	int arr[4];		//int arr
	char ch[5];		//char ch
}

数组元素下标是从0开始的

#include<stdio.h>
int main(void)
{
	int arr[] = { 1,2,3,4,5,6,7 };
	printf("%d\n", arr[6]);
	//arr[6]找到数组下标为7的数组元素
	return 0;
}

运行结果:

7
#include<stdio.h>
int main(void)
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int i = 0;
	for (i == 0; i < 10; i++)	//循环打印数组arr中的所有元素
	{
		printf("%d\n", arr[i]);
	}
	return 0;
}

运行结果:

1
2
3
4
5
6
7
8
9
10

以下也是不完全初始化,只将第一个元素初始化为0,剩余的元素均为0

#include<stdio.h>
int main(void)
{
	int arr[10] = { 0 };
	return 0;
}

计算机处理的数据,都要加载到内存中处理

内存会被划分成一个个的内存单元,然后给每个内存单元都编号

一个内存单元大小是一个字节

#include<stdio.h>
int main(void)
{
	int arr[] = { 0 };
	int i = 0;
	for (i = 0; i < 10; i++)	//循环打印数组arr中的所有元素
	{
		printf("&arr[%d]=%p\n", i,arr[i]);		//%p是取地址符号
	}
	return 0;
}

运行结果:

&arr[0]=00000000
&arr[1]=CCCCCCCC
&arr[2]=C3AC8F8D
&arr[3]=00DCF998
&arr[4]=006320D3
&arr[5]=00000001
&arr[6]=012EAEF0
&arr[7]=012E32B0
&arr[8]=00000001
&arr[9]=012EAEF0

不难发现,一维数组的地址是连续递增的,随着数组下标的增长一直是由小到大变化的,各个相邻的元素之间相差4

sizeof计算数组元素的大小

sizeof能够计算变量所占内存空间大小,单位是字节

sizeof计算的是变量或者类型的长度,单位是字节

#include<stdio.h>
int main(void)
{
	int arr[10] = { 0 }; 
	printf("%d\n", sizeof(arr));    //计算的是数组的总大小,单位是字节
    printf("%d\n", sizeof(arr[0]));		//求数组第一个元素的大小
    printf("%d\n", sizeof(arr)/sizeof(arr[0]));		//求有几个数组元素
    return 0;
}

运行结果:

40
4
10

二维数组的初始化

type arr_name[常量值][常量值];
例如:
int arr[3][5];    //[3][5]分别是行和列
double data[3][5];

1、不完全初始化 

#include<stdio.h>
int main(void)
{
	int arr[3][5] = { 1,2,3,4,5 };	//不完全初始化
	//依次初始化每一行,当不够的时候,剩余的元素初始化为0
    //只初始化了第一行
	return 0;
}

2、完全初始化

#include<stdio.h>
int main(void)
{
	int arr[3][5] = {
		{ 1,2,3,4,5},
		{ 1,2,3,4,5},
		{ 1,2,3,4,5}
	};
	printf("%d", arr[3][5]);
	return 0;
}

初始化的时候可以省略行,但不能省略列

#include<stdio.h>
int main(void)
{
	int arr[][5] = {
		{ 1,2,3,4,5},
		{ 1,2,3,4,5},
		{ 1,2,3,4,5}
	};
	return 0;
}

二维数组的下标行和列都是从0开始的

#include<stdio.h>
int main(void)
{
	int arr[3][5] = {
		{ 1,2,3,4,5,},
		{ 1,2,3,4,5,},
		{ 1,2,3,4,5,}
	};
	printf("%d", arr[1][4]);	//打印5
	//不完全初始化
	//依次初始化每一行,当不够的时候,剩余的元素初始化为0
	return 0;
}

运行结果:

5
#include<stdio.h>
int main(void)
{
	int arr[3][5] = { 0 };
	int i = 0;
	printf(">");
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{	
			scanf("%d", &arr[i][j]);
		}
	}
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

运行结果:

>1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5

 打印二维数组中所有元素的地址

#include<stdio.h>
int main(void)
{
	int arr[3][5] = { 0 };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("&arr[%d][%d]=%p\n", i,j,&arr[i][j]);
		}
	}
	return 0;
}

运行结果:

&arr[0][0]=003FFD74
&arr[0][1]=003FFD78
&arr[0][2]=003FFD7C
&arr[0][3]=003FFD80
&arr[0][4]=003FFD84
&arr[1][0]=003FFD88
&arr[1][1]=003FFD8C
&arr[1][2]=003FFD90
&arr[1][3]=003FFD94
&arr[1][4]=003FFD98
&arr[2][0]=003FFD9C
&arr[2][1]=003FFDA0
&arr[2][2]=003FFDA4
&arr[2][3]=003FFDA8
&arr[2][4]=003FFDAC

每行相邻元素之间相差4

二维数组在内存中也是连续存放的

二维数组是一个一维数组的数组

存放一维数组的数组

二维数组的每个元素是一维数组

变长数组

变长数组的根本特征,就是数组长度只有运行时才能确定,所以变长数组不能初始化。变长数组的好处是程序员不必在开发时,随意为数组指定一个估计的长度,程序可以在运行时为数组分配精确的长度。

1、多个字符从两端向中间移动

#include<stdio.h>
#include<windows.h>		//引用Sleep()函数
#include<string.h>
#include<stdlib.h>		//引用system()函数
int main(void)
{
	char arr1[] = "welcome bo bit";
	char arr2[] = "##############";
	int left = 0;
	int right = strlen(arr1) - 1;
	//字符串求长度=长度-1
	while (left<=right)
	{
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		printf("%s\n", arr2);
		//实现打印一行清空一行的效果
		Sleep(1000);	//单位是毫秒,使用此函数可以一秒打印一行
		system("cls");	//system函数是库函数,可以执行系统指令,cls可以清理控制台屏幕信息
		left++;
		right--;
	}
	printf("%s\n", arr2);	
	//以上函数体内的代码打印完成之后最后一次会清空屏幕
	//想要看到全部则需要再次打印一次arr2数组
	return 0;
}
printf("%d", strlen(arr1));    //函数求的字符串长度是带结束符'\0'的
printf("%d", sizeof(arr1));    //函数求得字符串长度是不带结束符'\0'的

2、二分查找(折半查找)

折半查找原理,(数组的左下标+数组的右下标)/2,除完之后小数部分直接舍弃

 一次折半查找的过程:

1、确定被查找的范围

2、确定被查找范围的左右下标

3、根据左右下标确定中间元素的下标

4、根据中间元素和要找的元素进行比较

5、如果找到则结束,找不到根据大小关系确定新的查找范围

//常规的顺序查找
#include<stdio.h>
int main(void)
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };	//升序数组
	//在数组中查找key
	int key = 0;
    printf(">");
	scanf("%d", &key);
	int sz = sizeof(arr) / sizeof(arr[0]);		//sz的值为数组arr的长度包含结束符
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		if (arr[i] == key)
		{
			printf("找到了下标是%d\n",i);
			break;
		}
	}
	if (i == sz)
	{
		printf("找不到了\n");
	}
	return 0;
}

运行结果:

>8
找到了下标是7
#include<stdio.h>
int main(void)
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 0;
	printf(">");
	scanf("%d", &k);
	int sz = sizeof(arr) / sizeof(arr[0]);
	int left = 0;
	int right = sz - 1;
	while (left <= right)
	{
		int mid = (left + right) / 2;
		if (arr[mid] == k)
		{
			printf("找到了,下标是:%d\n", mid);
			break;	//找到后跳出循环
		}
		else if (arr[mid] < k)
		{
			left = mid + 1;
		}
		else
		{
			right = mid - 1;
		}
	}
	if (left > right)
	{
		printf("找不到\n");
	}
	return 0;
}

运行结果:

>5
找到了,下标是:4

 优化:

加入标签flag

#include<stdio.h>
int main(void)
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 0;
	printf(">");
	scanf("%d", &k);
	int sz = sizeof(arr) / sizeof(arr[0]);    //求元素个数,包含结束符
	int left = 0;
	int right = sz - 1;    //将结束符占用的空间去掉
	int flag = 0;
	while (left <= right)
	{
		int mid = (left + right) / 2;
		if (arr[mid] == k)
		{
			printf("找到了,下标是:%d\n", mid);
			flag = 1;    //flag标签
			break;	//找到后跳出循环
		}
		else if (arr[mid] < k)
		{
			left = mid + 1;
		}
		else
		{
			right = mid - 1;
		}
	}
	if (flag==0)
	{
		printf("找不到\n");
	}
	return 0;
}

使用折半查找的数组必须是有序的

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黄金圣手

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值