数组理论基础

一维数组

数组是计算机科学中最基本的数据结构之一

数组的概念:存放在连续内存空间上的相同类型数据的集合

【eg.】将10个整型数据1-10存放在数组arr中

c 复制代码
int arr[10] = {1,2,3,4,5,6,7,8,9,10};

每个数组元素都有下标,下标都是从 0 开始

使用下标来访问数组中的每个元素,eg. arr[0] 对应数组的第一个元素

一维数组的创建和初始化

数组的创建

一维数组的创建方式如下:

c 复制代码
type_t arr_name [const_n];
//type_t 是指数组的元素类型
//arr_name 是数组名
//const_n 是一个常量表达式,用于指定数组的大小

下面例举一些数组创建的实例:

c 复制代码
//代码1
int arr1[10];

//代码2 <🚩错误示例>
int count = 10;		//count是变量
int arr2[count];	//[]中需要的是常量表达式

//代码3
char arr3[10];
float arr4[1];
double arr5[20];

注意 】数组创建,[] 中要给常量才可以,不能使用变量(如果支持C99,那么可以使用变量,即创建变长数组)

数组的初始化

数组的初始化是指在创建数组的同时给数组元素赋初始值(初始化)

初始化分为完全初始化不完全初始化,下面举例说明:

  • 完全初始化

    c 复制代码
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
  • 不完全初始化

    c 复制代码
    int arr[10] = {1,2,3,4,5};

    没有赋值的元素默认为 0

下面例举一些数组初始化的实例:

c 复制代码
int arr1[10] = {1,2,3};
int arr2[] = {1,2,3,4,5};
int arr3[5] = {1,2,3,4,5};	//arr2 和 arr3 是一样的效果
char arr4[3] = {'a',98,'c'};
char arr5[] = {'a','b','c'}; //这个数组的长度是3,但是求得的字符串长度是随机值,因为字符串以'\0'为结束标志
char arr6[] = "abc";	//用数组表示字符串,数组元素是:a b c \0 (一共4个元素,注意和 arr5 区分)
char arr7[5] = "abc";	//数组元素是:a b c \0 \0

一维数组的使用

操作符:[] 是下标引用操作符,就是数组访问的操作符

c 复制代码
#include <stdio.h>
int main(){
    int arr[10] = {0};	//数组不完全初始化
    
    //计算数组的元素个数
    int sz = sizeof(arr)/sizeof(arr[0]);
    
    //对数组元素赋值(数组是使用下标来访问的,下标从 0 开始)
    for(int i = 0;i < 10;i++){
        arr[i] = i;
    }
    
    //输出数组内容
    for(int i = 0;i < 10;i++){
        printf("%d ",arr[i]);
    }
    
    return 0;
}

总结

  • 数组是使用下标来访问的,下标是从0开始的
  • 数组大小可以通过计算得到

一维数组在内存中的存储

c 复制代码
#include <stdio.h>

int main() {
	int arr[10] = {0};
	int i = 0;
	for (i = 0; i < 10; i++) {
		printf("&arr[%d] = %p\n", i, &arr[i]);
        // %p :按地址的格式打印 ------ 十六进制的打印
	}
	return 0;
}

总结

  1. 一维数组在内存中是连续存放的
  2. 随着数组下标的增长,地址是由低到高变化的

因为数组是连续存储的,所以当我们知道数组的首元素地址时,就可以找到数组中所有的元素

c 复制代码
#include <stdio.h>

int main() {
	int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    
    int* p = arr; //数组名是数组首元素的地址
    //让指针 p 指向数组 arr 的第一个元素,也就是 &arr[0]
    
	int i = 0;
	for (i = 0; i < 10; i++) {
		printf("%d\n", *p);	//*p 表示 "取出 p 所指向地址中的值"(解引用)
        p++;	//指针移动到下一个 int 元素
	}
	return 0;
}

//输出:
1 2 3 4 5 6 7 8 9 10

二维数组

C语言提供了类似矩阵 多维数组

【二维数组可以看作是一维数组,数组中的每个元素也是数组】

二维数组的创建和初始化

二维数组的创建

c 复制代码
int arr1[3][4];
char arr2[3][5];
double arr3[2][4];

二维数组的初始化

c 复制代码
int arr1[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};	//完全初始化
c 复制代码
int arr2[3][4] = {1,2,3,4,5,6,7};	//不完全初始化,未赋值部分补0
c 复制代码
int arr3[3][4] = { {1,2},{3,4},{5,6} };		//一行一行地初始化

【注意】二维数组初始化时行数可以省略 ,但是列数不可以省略

c 复制代码
int arr4[][4] = { {1,2},{3,4},{5,6} };

二维数组的使用

二维数组的使用也是通过下标的方式

c 复制代码
#include <stdio.h>

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

//输出:
1 2 0 0
3 4 0 0
5 6 0 0

二维数组在内存中的存储

c 复制代码
#include <stdio.h>

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

总结二维数组在内存中也是连续存放的,每一行内部是连续的,行与行之间也是连续的

数组作为函数参数

在很多时候需要将数组作为函数参数传递,比如:冒泡排序函数将一个整型数组排序

冒泡排序函数的错误设计

c 复制代码
//方法1
#include <stdio.h>

void bubble_sort(int arr[]){	//形参 arr 本质上是指针,是数组首元素地址
    //计算数组元素个数,确定冒泡排序趟数
    int sz = sizeof(arr)/sizeof(arr[0]);	//🚩 错误
    int i = 0;
    for(i = 0; i < sz-1; i++){
        //一趟冒泡排序的过程
        int j = 0;
        for(j = 0; j < sz-1-i; j++){
            if(arr[j] > arr[j+1]){
                //交换
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }
}

int main(){
    int arr[] = {9,8,7,6,5,4,3,2,1};	//需要将数组排序为升序
    bubble_sort(arr);
    return 0;
}

修正:

c 复制代码
#include <stdio.h>

void bubble_sort(int arr[], int sz){
    int i = 0;
    for(i = 0; i < sz-1; i++){
        //一趟冒泡排序的过程
        int j = 0;
        for(j = 0; j < sz-1-i; j++){
            if(arr[j] > arr[j+1]){
                //交换
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }
}

int main(){
    int arr[] = {9,8,7,6,5,4,3,2,1};	//需要将数组排序为升序
    int sz = sizeof(arr)/sizeof(arr[0]);
    bubble_sort(arr,sz);
    return 0;
}

【注意】数组名是首元素地址

但是有两个例外情况:

  1. sizeof(数组名) --- 数组名表示整个数组 --- 计算的是整个数组的大小,单位是字节
  2. &数组名 --- 数组名表示整个数组 --- 取出的是整个数组的地址
c 复制代码
#include <stdio.h>

int main() {
    int arr[10] = { 0 };
    
    printf("%p\n", &arr);
    printf("%p\n", &arr+1);

    printf("%p\n", arr);
    printf("%p\n", arr+1);

    return 0;
}
相关推荐
细心的莽夫1 小时前
SpringCloud 微服务复习笔记
java·spring boot·笔记·后端·spring·spring cloud·微服务
石去皿1 小时前
力扣hot100 91-100记录
算法·leetcode·职场和发展
BOB-wangbaohai2 小时前
Flowable7.x学习笔记(十三)查看部署流程图
笔记·学习·流程图
圣保罗的大教堂2 小时前
leetcode 2799. 统计完全子数组的数目 中等
leetcode
SsummerC2 小时前
【leetcode100】组合总和Ⅳ
数据结构·python·算法·leetcode·动态规划
2301_807611493 小时前
77. 组合
c++·算法·leetcode·深度优先·回溯
bicijinlian4 小时前
多语言笔记系列:使用导入魔法命令
笔记
SsummerC4 小时前
【leetcode100】零钱兑换Ⅱ
数据结构·python·算法·leetcode·动态规划
程序员-King.5 小时前
day47—双指针-平方数之和(LeetCode-633)
算法·leetcode