学习笔记 | C语言中的数组

数组的概念

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

  • 数组中存放的是1个或多个数据,但是数组元素个数不能为 0 。
  • 数组中存放的多个数据,类型是相同的。

数组可以分为一维数组,多维数组;常见的是二维数组。

一维数组

创建和初始化

ini 复制代码
type arr_name[常量值];
​
数组类型 数组名称[元素个数];

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

数组的创建

ini 复制代码
int math[20];

数组的初始化

csharp 复制代码
int main()
{
    int num[5] = {1,2,3,4,5};//完全初始化:创建数组,并且初始化1,2,3,4,5
    
    int num2[5] = {1,2,3};//不完全初始化,剩余的元素初始化为 0
    
    int num3[] = {1,2,3};//如果数组初始化了,是可以省略数组大小
    //数组的大小,编译器根据初始化的内容确定
    
    int num4[5] = {1,2,3,4,5,6};//报错
    return 0;
}

数组的类型

数组属于自定义类型。

csharp 复制代码
int main()
{
    int num[5] = {1,2,3,4,5}; //num1的类型是 int [5]
    
    int num2[10] = {1,2,3}; //num2的类型是 int [10]
    
    int num3[] = {1,2,3};
    
    return 0;
}

一维数组的使用

数组下标

arduino 复制代码
int arr[10] = {1,2,3,4,5,6,7,8,9,10};//对应的下标是 0 ~ 9
  • 下标是从0开始,最后一个元素的下标是n-1
  • C 语言中使用下标访问数组中的数据
  • 为下标访问操作符
ini 复制代码
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
    //打印 7
    printf("%d\n", arr[6]);
​
    int i = 0;
    //循环打印所有数组
    for (i = 0; i < 10;i++)
    {
        printf("%d ", arr1[i]);
    }
​
​
    return 0;
}

执行结果

C99标准之前,数组的大小只能是常量指定

数组在内存中的存储

观察数字在内存中的地址

ini 复制代码
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int i = 0;
    //循环打印所有数组
    for (i = 0; i < 10;i++)
    {
        printf("arr[%d] = %pn",i &arr1[i]);// %p 用来打印地址
    }
​
    return 0;
}

执行结果

  • 一维数组在内存中是连续存放的
  • 随着下标的增长,地址也是增长

sizeof计算数组的长度

c 复制代码
int main()
{
    int arr[10] = { 1,2,3 };//10 * 4
    printf("%d\n", sizeof(arr));//sizeof(数组)计算的是数组所占内存空间的大小,单位是字节
    printf("%d\n", sizeof(arr[0]));
    printf("%d\n", sizeof(arr) / sizeof(arr[0]));
    int sz = sizeof(arr) / sizeof(arr[0]);
    int i = 0;
    //循环打印所有数组
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
​
​
    }
    return 0;
}

执行结果

此时,数组元素个数的变化并不会影响代码的运行。

二维数组的创建初始化

如果把一维数组作为数组的元素,那就是二维数组。

二维数组的创建

ini 复制代码
type arr_name[常量值1][常量值2];
//例如
int arr [3][5];
  • 3 表示数组有 3 行
  • 5 表示每一行有 5 个元素
csharp 复制代码
int main()
{
    double score[20][5];
    
    return 0;
}

全初始化

ini 复制代码
int main()
{
    //不完全初始化
    int score1[3][5] = {1,2};
    int score2[3][5] = {0};
    int score3[3][5] = {1,2,3,4,5,6,7};
    int score3[3][5] = {{1,2},{3,4},{5,6}};//指定1,2放入第一行,3,4放入第二行;以此类推
    //完全初始化
    int score4[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
    return 0;
}

二维数组初始化时,行可以省略,但是列不能省略

csharp 复制代码
int main()
{
    int score1[][5] = {1,2}; //初始化了一行
    int score3[][5] = {1,2,3,4,5,6,7};//初始化了两行
    int score3[][5] = {{1,2},{3,4},{5,6}};//初始化了三行
    return 0;
}

打印指定数组和所有数组

三行五列的数组:[3][5]

下标 0 1 2 3 4
0 1 2 3 4 5
1 2 3 4 5 6
2 3 4 5 6 7
ini 复制代码
int main()
{
    int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
    printf("%d\n", arr[1][3]);//打印第二行第四个数字 5
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        int j = 0;
        for (j = 0; j < 5; j++)
        {
            printf("%d", arr[i][j]);
        }
        printf("\n");
​
    }
​
    return 0;
}

执行结果

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

arr1[]

arr2[][]

C99中的变长数组

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

如:

ini 复制代码
int arr1[10];
int arr2[3+5];
int arr3[] = {1,2,3};

C99标准之后,引入了变长数组的概念,允许数组的大小是变量。

arduino 复制代码
int main()
{
    int n = 0;
    scanf("%d",&n);
    int arr[n];
    return 0;
}
  • VS虽然支持了C99的语法,但是并不是完全支持。比如变长数组。
  • 变长数组不能初始化

变长数组中,变长的概念是数组的长度可以引用变量,而不仅仅使用常量。并不是说数组可以任意改变其大小。

数组练习

多个字符从两端移动,向中间汇聚

打印内容如下:welcome to C !!!!!!!!!!

markdown 复制代码
//***********************
//w*********************!
//we*******************!!
//以此类推,最终打印
//welcome to C !!!!!!!!!!

代码实现

ini 复制代码
#include <string.h>
int main()
{
    char arr1[] = "welcome to C !!!!!!!!!!";
    char arr2[] = "***********************";
    
    int left = 0;
    int right = strlen(arr1)-1;
    
    while(left<=right)
    {
        arr2[left] = arr1[left];
        arr2[right] = arr1[right];
        printf("%s\n",arr2);
        left++;
        right--;
    }
    return 0;
}

执行结果

添加动态效果

  • Sleep(1000); //休眠一秒。需要引入头文件,windows.h

在一行上像两端移动

  • system("cls");

最终代码

scss 复制代码
#include <string.h>
int main()
{
    char arr1[] = "welcome to C !!!!!!!!!!";
    char arr2[] = "***********************";
    
    int left = 0;
    int right = strlen(arr1)-1;
    
    while(left<=right)
    {
        arr2[left] = arr1[left];
        arr2[right] = arr1[right];
        printf("%s\n",arr2);
        Sleep(1000);
        system("cls");
        left++;
        right--;
    }
    printf("%s\n",arr2);
    return 0;
}

动态效果,自行验证。

二分查找

在一个指定的有序数组中查找指定的数字n,也叫折半查找。

例如:

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

int k = 7;

在arr数组中,找 7

遍历查找法

ini 复制代码
int main()
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    int k = 0;
    scanf("%d", &k);
    int i = 0;
    int sz = sizeof(arr) / sizeof(arr[0]);
    int find = 0;//假设找不到
    for (i = 0; i < sz; i++)
    {
        if (k == arr[i])
        {
            printf("找到了,下标是%d\n", i);
            find = 1;
            break;
        }
    }
    if (find == 0)
    {
        printf("找不到\n");
    }
    return 0;
}

执行结果

二分查找算法

ini 复制代码
Mid = (L + R)/2;
  • Mid:中间位
  • L:最左下标
  • R:最右下标

代码

ini 复制代码
int main()
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    int k = 0;
    int sz = sizeof(arr) / sizeof(arr[0]);
    scanf("%d", &k);
    //使用二分查找
    int left = 0;
    int right = sz - 1;
    int find = 0;//假设找不到
​
    
    while (left <= right)
    {
        //int mid = (left + right) / 2;//这种写法在left和right都非常大,接近int的最大值的时候会有问题.
        int mid = left + (right - left) / 2;
        if (arr[mid] < k)
        {
            left = mid + 1;
        }
        else if (arr[mid] > k)
        {
            right = mid - 1;
        }
        else
        {
            printf("找到了,下标是%d\n", mid);
            find = 1;
            break;
        }
    }
    if (find == 0)
    {
        printf("找不到了");
    }
    return 0;
}

执行结果

注意:

二分查找的前提条件是数组必须是有序的

时间复杂度为O(Log₂n)

相关推荐
芜湖_16 小时前
【山大909算法题】2014-T1
算法·c·单链表
时光の尘20 小时前
C语言菜鸟入门·关键字·float以及double的用法
运维·服务器·c语言·开发语言·stm32·单片机·c
理论最高的吻2 天前
98. 验证二叉搜索树【 力扣(LeetCode) 】
数据结构·c++·算法·leetcode·职场和发展·二叉树·c
时光の尘2 天前
C语言菜鸟入门·关键字·void的用法
c语言·开发语言·c++·算法·c#·c·关键字
神一样的老师3 天前
C/C++ 优化,strlen 示例
c
万物复苏1015 天前
【汇编】c++游戏开发
开发语言·笔记·游戏·c
石牌桥网管7 天前
用正则表达式检查是IP否为内网地址
java·c++·golang·正则表达式·php·c
Koishi_TvT8 天前
蓝桥杯c++算法学习【3】之思维与贪心(重复字符串、翻硬币、乘积最大、皮亚诺曲线距离【难】:::非常典型的必刷例题!!!)
c++·学习·算法·游戏·贪心算法·蓝桥杯·c
Ustinian_31011 天前
【C++】 C++游戏设计---五子棋小游戏
c
一叶飘零_sweeeet12 天前
Spring Boot 的核心注解
java·spring boot·c