C语言的数组

对于上一节的项目实战,大家可能都有点兴趣。那么这节我们就来一起学习C语言数组的相关知识吧。

在开始之前先考虑下面两个问题:

1.输入100个数并以与输入时相反的顺序输出这100个数。

2.输入100个学生的成绩,输出高于平均分的那些成绩


一、概述

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

特点:所有数据元素类型相同、可以存储一个及以上的同类型元素

要素:数组名,集合类型,下标。


二、一维数组

1.一维数组的定义

*定义方式:

类型说明符 数组名[整型常量表达式];

#define Length 100
char ch[Length];
int arr[10];
double arr2[5*3];

*说明:命名规则、数组长度、下标、数组类型

数组的命名规则和变量的命名类似,在此基础上加上[常量值]即可,[]是一种操作符,叫做下标引用操作符,用来访问数组元素的。数组是一种特殊的变量,它也是有类型的,例如int arr[10]的数据类型就是int [10]。数组的长度可以使用sizeof()运算符获取:

int arr[10]={0};
int length_arr = sizeof(arr)/sizeof(int);//10
2.一维数组的引用

*引用方式:数组名[下标];

如a[0],x[i],y[2*i-1];

例:

main()
{
    int a[100];
    for(int i=0;i<100;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i=0;i<sizeof(a)/sizeof(int);i++)
    {
        printf("%4d",a[99-i]);
    }
}

将a[i]当作一个int类型的数据,再看这段代码,是不是就不吃力了。这时候转换回来,再看a[i],这就是对数组元素的引用。

3.一维数组的初始化

*在定义数组时,对全部数组元素赋初值。

*只给一部分元素赋初值

*定义数组时使数组中全部元素自动赋0值

int arr[5]={0,1,2,3,4};//全部初始化

int arr[5]={6,2};//部分初始化
int arr[5]={6,2,0,0,0};//与上一行等价

int arr[5]={0};//全部赋0值
static int arr[5];//静态变量定义时不初始化,则自动初始化为0

*对全部元素赋初值时,可以不指定数组长度。

int arr[3]={1,2,3};
int arr[]={1,2,3};//二者完全等价
//后者[]中隐藏数字3
4.相关算法介绍
(1)Fibonacci数列问题
//用数组求斐波那契数列前四十项
int main()
{
    long f[40]={1,1};
    for(int i=2;i<40;i++)
        f[i]=f[i-1]+f[i-2];
    for(int i=0;i<40;i++)
    {
        if(i%5==0)printf("\n");//换行
        printf("%12ld",f[i]);
    }
    return 0;
}
(2)找最值
//举例寻求最大值
int main()
{
    int arr[10]={0};
    for(int i=0;I<10;i++)scanf("%d",&arr[i]);
    int max=arr[0];
    for(int i=1;i<10;i++)
    {
        if(arr[i]>max) max=arr[i];
    }
    printf("最大值:%d",max);
}
(3)数组合并
int* Add(int arr1[], int arr2[])
{
	//将arr2并入arr1
	const int len1 = sizeof(arr1) / sizeof(int);
	const int len2 = sizeof(arr2) / sizeof(int);
	int arr[len1+len2] = { 0 };
	for (int i = 0; i < len1; i++)
	{
		arr[i] = arr1[i];
	}
	for (int i = len1; i < len1 + len2; i++)
	{
		arr[i] = arr2[i - len1];
	}
	return arr;
}
(4)排序问题
冒泡排序
void BubbleSort(int *arr, int size)  
{  
    int i, j, tmp;  
    for (i = 0; i < size - 1; i++) 
    {  
        for (j = 0; j < size - i - 1; j++) 
        {  
            if (arr[j] > arr[j+1])
             {  
                tmp = arr[j];  
                arr[j] = arr[j+1];  
                arr[j+1] = tmp;  
            }  
        }  
    }  
}  
选择排序
void SelectionSort(int *arr, int size)
{
    int i, j, k, tmp;
    for (i = 0; i < size - 1; i++) 
    {
        k = i;
        for (j = i + 1; j < size; j++) 
        {
            if (arr[j] < arr[k])
             {
                k = j;
            }
        }
        tmp = arr[k];
        arr[k] = arr[i];
        arr[i] = tmp;
    }
}
插入排序
void InsertionSort(int *arr, int size)    
{    
    int i, j, tmp;    
    for (i = 1; i < size; i++) 
    {    
        if (arr[i] < arr[i-1])
        {    
            tmp = arr[i];    
            for (j = i - 1; j >= 0 && arr[j] > tmp; j--) 
            {  
                arr[j+1] = arr[j];    
            }  
            arr[j+1] = tmp;    
        }          
    }    
}    
希尔排序
void ShellSort(int *arr, int size)  
{  
    int i, j, tmp, increment;  
    for (increment = size/ 2; increment > 0; increment /= 2) 
    {    
        for (i = increment; i < size; i++) 
        {  
            tmp = arr[i];  
            for (j = i - increment; j >= 0 && tmp < arr[j]; j -= increment) 
            {  
                arr[j + increment] = arr[j];  
            }  
            arr[j + increment] = tmp;
        }  
    }  
}  
归并排序(数组、递归、函数)
#define MAXSIZE 100  
 
void Merge(int *SR, int *TR, int i, int middle, int rightend) 
{
    int j, k, l;  
    for (k = i, j = middle + 1; i <= middle && j <= rightend; k++) {  
        if (SR[i] < SR[j]) {
            TR[k] = SR[i++];
        } else { 
            TR[k] = SR[j++];
        }  
    }  
    if (i <= middle) {
        for (l = 0; l <= middle - i; l++) {
            TR[k + l] = SR[i + l];
        }  
    }  
    if (j <= rightend) {
        for (l = 0; l <= rightend - j; l++) {
            TR[k + l] = SR[j + l];  
        }
    }  
}  
  
void MergeSort(int *SR, int *TR1, int s, int t) 
{  
    int middle;  
    int TR2[MAXSIZE + 1];  
    if (s == t) {
        TR1[s] = SR[s]; 
    } else {  
        middle = (s + t) / 2;
        MergeSort(SR, TR2, s, middle);
        MergeSort(SR, TR2, middle + 1, t);
        Merge(TR2, TR1, s, middle, t);
    }  
}  
快速排序(数组、递归、函数)
void QuickSort(int *arr, int maxlen, int begin, int end)  
{  
    int i, j;  
    if (begin < end) {  
        i = begin + 1;  
        j = end;        
        while (i < j) {  
            if(arr[i] > arr[begin]) {  
                swap(&arr[i], &arr[j]); 
                j--;  
            } else {  
                i++; 
            }  
        }  
        if (arr[i] >= arr[begin]) {  
            i--;  
        }  
        swap(&arr[begin], &arr[i]);      
        QuickSort(arr, maxlen, begin, i);  
        QuickSort(arr, maxlen, j, end);  
    }  
}  
 
void swap(int *a, int *b)    
{  
    int temp;  
    temp = *a;  
    *a = *b;  
    *b = temp;  
}  
桶排序(进阶)
void bucketSort(int *arr, int size, int max)
{
    int i,j;
    int buckets[max];
    memset(buckets, 0, max * sizeof(int));
    for (i = 0; i < size; i++) {
        buckets[arr[i]]++; 
    }
    for (i = 0, j = 0; i < max; i++) {
        while((buckets[i]--) >0)
            arr[j++] = i;
    }
}
堆排序(进阶)
void Heapify(int *arr, int m, int size)  
{  
    int i, tmp;  
    tmp = arr[m];  
    for (i = 2 * m; i <= size; i *= 2) {  
        if (i + 1 <= size && arr[i] < arr[i+1]) {  
            i++;  
        }  
        if (arr[i] < tmp) {  
            break;  
        }  
        arr[m] = arr[i];  
        m = i;  
    }  
    arr[m] = tmp;  
}  
  
void BulidHeap(int *arr, int size)
{  
    int i;  
    for (i = n / 2; i > 0; i--) {  
        Heapify(arr, i, size);  
    }  
}  
    
void swap(int *arr, int i, int j)  
{  
    int tmp;  
    tmp = arr[i];  
    arr[i] = arr[j];  
    arr[j] = tmp;  
}  
  
void HeapSort(int *arr, int size)  
{  
    int i;  
    BulidHeap(arr, size);  
    for (i = size; i > 1; i--) {  
        swap(arr, 1, i);
        Heapify(arr, 1, i - 1);
    }  
}  
计数排序(进阶)
void CountingSort(int *A, int *B, int n, int k)  
{  
    int *C = (int *)malloc(sizeof(int) * (k + 1));  
    int i;  
    for (i = 0; i <= k; i++) {  
        C[i] = 0;  
    }  
    for (i = 0; i < n; i++) {  
        C[A[i]]++;  
    }  
    for (i = 1; i <= k; i++) {  
        C[i] = C[i] + C[i - 1];  
    }  
    for (i = n - 1; i >= 0; i--) {  
        B[C[A[i]] - 1] = A[i];  
        C[A[i]]--;  
    }  
}  
基数排序(进阶)
int get_index(int num, int dec, int order)
{
    int i, j, n;
    int index;
    int div;
    for (i = dec; i > order; i--) {
        n = 1;
        for (j = 0; j < dec - 1; j++)
            n *= 10;
        div = num / n;
        num -= div * n;
        dec--;
    }
    n = 1;
    for (i = 0; i < order - 1; i++)
        n *= 10;
    index = num / n;
    return index;
}
 
void RadixSort(int *arr, int len, int dec, int order)
{
    int i, j;
    int index; 
    int tmp[len]; 
    int num[10];
    memset(num, 0, 10 * sizeof(int)); 
    memset(tmp, 0, len * sizeof(int));
 
    if (dec < order) {
        return;
    }
    for (i = 0; i < len; i++) {
        index = get_index(arr[i], dec, order);
        num[index]++; 
    }
 
    for (i = 1; i < 10; i++) {
        num[i] += num[i-1];
    }
    for (i = len - 1; i >= 0; i--) {
        index = get_index(arr[i], dec, order); 
        j = --num[index]; 
        tmp[j] = arr[i]; 
    }
 
    for (i = 0; i < len; i++) {
        arr[i] = tmp[i]; 
    }
    RadixSort(arr, len, dec, order+1);
}
(5)逆序重放
void Reserve(int arr[])
{
	int len = sizeof(arr) / sizeof(int) - 1;
	for (int i = 0; i <= len / 2; i++)
	{
		int tmp = arr[i];
		arr[i] = arr[len - i];
		arr[len - i] = tmp;
	}
}


三、二维数组

1.二维数组的定义

前面学习的数组被称为一维数组,数组的元素都是内置类型的,如果我们把一维数组作为数组的元素,这时候就是二维数组。二维数组作为数组元素创建的数组称为三维数组,但二维以上统称为多维数组。

那么二维数组如何定义和创建呢?类比一维数组就有:(二维数组的引用同一位数组一样)

int arr[3][5];
char ch[5][3];
2.二维数组的初始化

*对全部元素赋值

int arr[3][3]={{0,1,2},{1,2,3},{2,3,4}};
int arr[3][3]={0,1,2,1,2,3,2,3,4};
int arr[][3]={0,1,2,1,2,3,2,3,4};

//初始化可以省略行,不能省略列

*对部分元素赋值

int arr[3][3]={{1,2,3},{2,3,4}};

int arr[3][3]={{1,2,0},{2,4,0}}
int arr[3][3]={{1,2},{2,4}};//等价于上行

int arr[3][3]={{1,2,2},{4}};
int arr[3][3]={1,2,2,4};//等价于商上一行

二维数组赋值也就那么几种形式,大家可以回去琢磨一下,亲自上手实践。


四、字符数组

字符数组是数组元素都是char类型的一种特殊数组,学习本节内容有很大的实际运用意义,例如打印图形,了解ASCII码对应的字符等。

1.字符数组的定义

定义方法无非是数据类型是char类型。

char ch[10];
char c[2][5];
2.字符数组的初始化

*将字符数组中的各元素逐个赋予字符

*用字符串常量来对字符数组初始化

char ch[5]={'t','a','b','l','e'};

char str[]="geography";
char str[10]="geography";//二者等价

const char str[10]="geography";
const char *str="geography";//二者等价

注:对静态字符数组未被赋值的元素系统自动将其赋值为空‘\0’;

注:使用字符串常量赋值时,要考虑字符串本身结尾有‘\0’存在,所以上述代码存了10个字符。

字符数组的引用:同简单数组。

3.字符数组的输入输出

%c逐个字符输入/输出;%s一次性输入/输出整个字符串。

举例:

void fuc01()
{
	char ch[6];
	scanf("%s",ch);
	printf("%s\n", ch);
}

void fuc02()
{
	char ch[6];
	for (int i = 0;i < 6;i++)
	{
		scanf("%c", &ch[i]);
	}	
	for (int i = 0;i < 6;i++)
	{
		printf("%c", ch[6]);
	}
}

输入输出时应注意:第一、“%s”输入,后面跟数组名,不带&符;第二、用scanf输入(%s格式)时,无法输入空格;第三、%s格式输出,遇到‘\0’时结束。printf函数输出项是字符数组名,不是数组元素。

4.字符的相关io函数
(1)字符输出函数---putchar();

(2)字符输入函数---getchar();

(3)字符串处理函数

gets(字符数组名)---字符串输入函数;

puts(字符数组名或字符串常量)---字符串输出函数;

5.<string.h>头文件介绍

strlen(str):求字符串有效长度

strcat(str1,str2):字符串连接

strcpy(str1,str2):字符串复制

strcmp(str1,str2):字符串比较//比较规则:字典序


五、指针数组

指针数组是数组每一个元素存储的都是另一个同类型数据的地址


六、自定义类型数组

自定义类型数组是数组存储的元素是自定义的数据类型,像struct、enum类型


*七、C99中的边长数组 

在C99标准之前,C语言在创建数组的时候,数组的大小指定只能使用常量、常量表达式,或者如果我们初始化数据时省略数组大小。但这样的语法限制,让我们创建数组时不够灵活,有时候数组大了浪费空间、有时候小了不够用。

C99中给了一个变长数组(Variable-Length Array,简称VAL)的新特性,允许我们使用变量指定数组大小。即:

int n;
scanf("%d",&n);
int arr[n];

变长数组的根本特征,就是数组长度只有运行时才能确定,所以变长数组不能初始化。它的好处是程序员不必在开发时,随意为数组指定一个估计的长度,程序可以在运行时为数组分配精确的长度。有一个比较迷惑的点,变长数组的意思是数组的大小是可以使用变量来指定的,在程序运行的时候,根据变量的大小来指定数组的元素个数,而不是说数组的大小是可变的。数组的大小一旦确定就不能再变化了。

注:vs2022上虽然支持大部分C99的语法,但不支持C99的边长数组,但可以使用gcc编译器测试验证(推荐Devc++)。大家可以复制这段代码测试结果。

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


感谢观看。

  • 20
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值