C语言一维数组(含数组二分查找)

一、数组的概念

  1. 概念:数组是⼀组相同类型元素的集合
  2. 特点:
    (1)数组中存放的是1个或者多个数据,但是数组元素个数不能为0
    (2)数组中存放的多个数据,类型是相同的
  3. 分类:数组分为⼀维数组和多维数组,多维数组⼀般⽐较多⻅的是⼆维数组

二、⼀维数组的创建和初始化

  1. 基本语法是:类型 数组名 [常量],存放在数组的值被称为数组的元素,数组在创建的时候可以指定数组的⼤⼩和数组的元素类型,例如: int arr[10],作用是创建一个可以存储10个整型元素的数组,这个数组的名称是 arr
  2. 基本结构解读:
    (1)类型:可以是int、float、double 、char 、short等等内置的数据类型,还可以是自定义的数据类型,以后会出专题讲解
    (2)数组名:可以任意指定,但是最好取有意义的名字,增加可读性
    (3)[]:里面放一个常量值用来代表数组中存放元素的个数,可以根据实际情况指定
  3. 例如:
int math[50];//存放某个班级50个同学的数学成绩,数据类型为整型
  1. 数组的初始化:
    (1)完全初始化:
int arr[5] = {1,2,3,4,5};//将数组的所有元素初始化就叫
                         //完全初始化

(2)不完全初始化:

int arr[6] = {1};//将数组第一个元素初始化为1
                 //其余元素默认初始化为0

(3)错误示范:

int arr[3] = {1,2,3,4,5};//数组原本就只定义了三个元素
                         //此时输入了五个元素,初始化项太多了
                         //容易产生数组越界访问的情况

三、⼀维数组的类型及使⽤

1.一维数组的类型:

    数组也是有类型的,数组算是⼀种⾃定义类型,去掉数组名留下的就是数组的类型,比如:

int arr[10];//类型为int [10]
char ch[5];//类型是char [5]

2.一维数组的使用:

(1)数组下标:

    数组的每一个元素都有一个下标,下标是从0开始的,通过下标可以访问数组中的每一个元素,比如以下数组:

int arr[10] = {1,2,3,4,5,6,7,8,9,10};

它的下标如图:
在这里插入图片描述

(2)[]操作符:

    在C语⾔中数组的访问提供了⼀个操作符 [] ,这个操作符叫:下标引⽤操作符。有了下标引用操作符,我们就可以轻松的访问到数组的元素了,⽐如我们访问下标为7的元素,我们就可以使⽤ arr[7] ,在上面那个数组中arr[7]所代表的元素是8,想要访问下标是3的元素,就可以使⽤ arr[3],在上面那个数组中arr[3]代表的元素就是4,比如:

在这里插入图片描述

(3)数组的打印:

    现在有如下数组:

int arr[10]={1,23,45,67,89,10}

    我们如何将数组的每一个元素打印出来呢?就要用到我们学过的循环语句,将变量i初始化为0,使用i当做数组的下标,将数组的元素一一打印,如图:
在这里插入图片描述

(4)数组的输入:

    假设有如下数组:

int arr[10] = { 0 };

    同打印数组一样,要使用循环,用i表示数组下标,如图先对数组进行挨个输入,再打印出来:
在这里插入图片描述

四、⼀维数组在内存中的存储

    为了直观的观察数组在内存中的存储,我们将数组中每一个元素的地址打印出来,使用的方法就是上面打印数组元素的方法,如图:
在这里插入图片描述
    这里的地址使用的是16进制表达,可以看出每一个元素的地址之间隔了4个字节,而刚好数组中存放的是整形元素,大小为4个字节,由此可以看出,数组在内存中的存储是连续的,是由低到高的,了解之后对我们以后学习指针帮助,这里暂且记住就行

五、sizeof计算数组元素个数

1.计算一维数组总大小:

    在遍历数组时,我们通常需要知道数组元素的个数,那么怎么求呢?我们可以用数组总大小除以数组单个元素的大小求到,求数组总大小就需要用到我们的sizeof操作符,具体方法如下:
在这里插入图片描述
    可以看到sizeof成功帮我们算出数组的总大小,为10*4==40个字节

2.计算一维数组的元素个数

    有了数组的总大小,求元素个数就很轻松了,如图:
在这里插入图片描述
    不要认为求元素个数没有用,在后面许多地方需要用到,最好掌握好

六、C99中的变⻓数组

    在C99标准之前,C语⾔在创建数组的时候,数组⼤⼩的指定只能使⽤常量、常量表达式,或者如果我们初始化数据的话,可以省略数组⼤⼩,如:

int arr[]={1,2,3,3};//编译器自动识别出元素个数为4

    这样的语法限制,让我们创建数组就不够灵活,有时候数组⼤了浪费空间,有时候数组⼜⼩了不够⽤,于是C99中给了⼀个变⻓数组的新特性,允许我们可以使⽤变量指定数组⼤⼩,比如:

int n = a+b;
int arr[n];

    上⾯⽰例中,数组 arr 就是变⻓数组,因为它的⻓度取决于变量 n 的值,编译器没法事先确定,只有运⾏时才能知道 n 是多少
    变⻓数组的根本特征,就是数组⻓度只有运⾏时才能确定,所以变⻓数组不能初始化。它的好处是程序员不必在开发时,随意为数组指定⼀个估计的⻓度,程序可以在运⾏时为数组分配精确的⻓度。有⼀个⽐较迷惑的点,变⻓数组的意思是数组的⼤⼩是可以使⽤变量来指定的,在程序运⾏的时候,根据变量的⼤⼩来指定数组的元素个数,⽽不是说数组的⼤⼩是可变的。数组的⼤⼩⼀旦确定就不能再变化了
    遗憾的是在VS2022上,虽然⽀持⼤部分C99的语法,但是默认没有⽀持C99中的变⻓数组,没法测,后面会专门写博客教大家如何在VS2022上使用变长数组,现在了解一下就可以了

七、数组练习

练习1.将字符串从两端移动,向中间汇聚(附源码)

例如:实现以下效果:
在这里插入图片描述
将我们要显示的字符串一步一步显现出来

1. 分析:

(1)我们可以创建两个数组,一个数组存放字符串“hello fanfan”,一个数组存放对应的* 号,如“************”,创建代码为:

char arr1[] = "hello fanfan";
char arr2[] = "************";
printf("%s\n",arr2);

(2)先打印*号数组,然后创建一个循环,每循环一次,就拿字符串数组“hello fanfan”最左边和最右边的字符替换 *数组最左边和最右边的字符,我们设最左边下标为left,右下标为right,访问最左边的字符可以用0下标表示,访问最右边的字符可以用元素长度减1的下标表示,如:

int left = 0;
int sz =sizeof(arr1)/sizeof(arr1[0]);
int right = sz-1;
while(left<=right)
{
   arr2[left] = arr1[left];
   arr2[right] = arr1[right];
   left++;
   right--;
   printf("%s\n", arr2);
}

(3)为了提升视觉效果,我们可以让它们每替换一个字符就暂停一秒,一秒之后再进行下一组替换,这样就更加好看了。我们需要引进一个函数,Sleep(),它的参数是一个无符号整型,单位是毫秒,想要暂停1秒,就是1000毫秒,要使用这个函数要包含头文件<windows.h>,如:

#include <windows.h>

Sleep(1000)

2.答案源码:

#include <stdio.h>
#include <windows.h>
int main()
{
	char arr1[] = "hello fanfan";
	char arr2[] = "************";
	int left = 0;
	int right = strlen(arr1) - 1;
	printf("%s\n", arr2);
	while (left<=right)
	{
		Sleep(1000);
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		left++;
		right--;
		printf("%s\n", arr2);
	}
	return 0;
}

练习2.二分查找

1.二分查找介绍:

    在⼀个升序的数组中查找指定的数字n,很容易想到的⽅法就是遍历数组,但是这种⽅法效率⽐较低。
    比如我们之前写的猜数字游戏,会生成一个随机数来让玩家猜,范围是1~100,那玩家会从1开始一个一个猜吗,不会吧,那样就太慢了,我们一般会从整体的一半开始猜,比如猜50,告诉你大了还是小了,这样只需要一步就可以排除庞大数字中的一半,比如假设猜1 ~ 10000,猜5000后就可以知道猜大了还是小了,直接排除了5000个数字,效率很快,这就是⼆分查找,也叫折半查找

2.要求:

    创建一个数组arr,里面包含1,2,3,4,5,6,7,8,9,10 共十个元素,用户输入一个值,然后通过二分查找快速查询用户输入的值是否在数组中,如果在就输出找到了,如果不在就输出找不到:

3.分析:

(1)根据二分查找我们需要找到中间元素,就可以用最左下标和最右下标的中间值,也就是它们的平均数,上例子我们介绍了最左下标和最右下标如何求,这里不再赘述,主要看看如何求中间下标:

    int left = 0;
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int left = 0;//左下标
	int right = sizeof(arr)/sizeof(arr[0])-1;//右下标
	int mid = (left + right)/2;//中间下标
    //为了避免left和right加起来的值大于了int能接受的最大值
    //可使用这样的方式:mid = left+ (right -left)/2

(2)随后我们用中间下标对应的元素与用户输入的值进行对比,看看是大了还是小了,如果大了那么就让right=min -1,如果小了就让left = mid +1,然后再用新的right或者left算出新的left,循环往复就可以找到对应的元素,找到后就在屏幕打印“找到了”,所以我们需要创建一个循环,具体实现如下:

	while (1)
	{
	    mid = left+ (right -left)/2;
		if (arr[mid] > num)
		{
			right = mid - 1;
		}
		else if (arr[mid] < num)
		{
			left = mid + 1;
			
		}
		else
		{
			printf("找到了\n");
			break;
		}

(3)当然,如果用户输入的值不在我们的数组中,我们就输出找不到,如:

        if (left > right)
		{
			printf("找不到\n");
			break;
		}

4.答案源码:

#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int mid = 0;//中间下标
	int left = 0;//左下标
	int right = sizeof(arr)/sizeof(arr[0])-1;//右下标

	int num = 0;//用于用户输入值
	printf("请输入:");
	scanf("%d", &num);

	while (1)
	{
		mid = (left + right) / 2;
		//为了避免left和right加起来的值大于了int能接受的最大值
        //可使用这样的方式:mid = left+ (right -left)/2
		if (arr[mid] > num)
		{
			right = mid - 1;
		}
		else if (arr[mid] < num)
		{
			left = mid + 1;
			
		}
		else
		{
			printf("找到了\n");
			break;
		}
		if (left > right)
		{
			printf("找不到\n");
			break;
		}
}
    return 0;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值