10.C语言- 数组

技术博客 (88) 2023-12-03 18:01:01

1.数组概念

存储一个固定大小的相同类型元素的顺序集合。数组是可以在内行中连续存储多个元素的结构,数组中的所有元素必须属于相同的数据类型。

10.C语言- 数组 (https://mushiming.com/) 技术博客 第1张

声明数组

type arrayName [ arraySize ];

初始化数组

double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};

10.C语言- 数组 (https://mushiming.com/) 技术博客 第2张

void main() {
  int a[5] = { 1,2,3,4,5 };
  printf("%p", a);//打印与a数组的首地址
  getchar();
}
10.C语言- 数组 (https://mushiming.com/) 技术博客 第3张

void main() {
  int a[5] = { 1,2,3,4,5 };
  printf("%p", a);//打印与a数组的首地址
  for (int i = 0; i < 5; i++)
  {
    a[i] = i + 5;
  }
  getchar();
}
10.C语言- 数组 (https://mushiming.com/) 技术博客 第4张

试一下double

void main() {
  //double 占8字节
  double a[3] = { 1.0,2.0,3.0 };
  printf("%p\n", a);
  printf("%d", sizeof(a));
  getchar();
}

按64位查看

10.C语言- 数组 (https://mushiming.com/) 技术博客 第5张

声明一个数组时,编译器为数组分配内存存储空间,值得注意的是:数组占据的内存空间是连续的,这样,很容易计算数组占据的内存大小和每个元素对应的内存首地址, 举例来说,对一个大小为N,类型为short的数组,其占据的内存大小为:N*2

通过个规律可以得出,第M个元素的地址:

p+(M−1)∗sizeof(type)p+(M-1)*sizeof(type) p+(M−1)∗sizeof(type)

2.维数组案例

将一个长度10的整形数组,反转输出。

void prinfArray(int x[], int num) {
  for (int i = 0; i < num; i++)
  {
    printf("%d,", x[i]);
  }
  printf("\n%s\n", "--------");
}

void main() {
  int x[] = { 1,2,3,4,5,6,7,8,9,10 };
  prinfArray(x, sizeof(x) / sizeof(x[0]));//计算出数组长度

  for (int i = 9; i >=0; i--)
  {
    printf("%d,", x[i]);
  }
}

数组求合与平均值

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

void main() {
  time_t ts;
  srand((unsigned)time(&ts));//设置时间随机数种子
  int a[10];
  for (int i = 0; i < 10; i++)
  {
    a[i] = rand() % 100;//取0到99之间的数
  }
  int sum = 0;
  double avg = 0.0;
  for (int i = 0; i < 10; i++)
  {
    sum += a[i];
  }
  avg = sum / 10.0;
  printf("合计:%d,平均数:%f", sum, avg);
  getchar();
}

随机生成一个数组,查找某一个数字是否存在于数组中

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int* initArray(int* a) {
  time_t ts;
  srand((unsigned)time(&ts));
  for (int i = 0; i < 99; i++)
  {
    a[i] = rand() % 100;
    printf("%d\n", a[i]);
  }
  return a;
}

void main() {
  int x = 0;
  scanf("%d", &x);
  int a[99];
  int* b = initArray(a);
  for (int i = 0; i < 99; i++)
  {
    if (b[i] == x) {
      printf("找到相应数据!%d", i);
      break;
    }
  }
}

斐波那契数列

void main() {
  int x[30];
  x[0] = 1;
  x[1] = 1;
  for (int i = 2; i < 30; i++)
  {
    x[i] = x[i - 1] + x[i - 2];
  }
  for (int i = 0; i < 30; i++)
  {
    printf("%d\n", x[i]);
  }
}

查找最大数与最小数

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>


void main() {
  time_t ts;
  int x[10];
  srand((unsigned)time(&ts));
  for (int i = 0; i < 10; i++)
  {
    x[i] = rand() % 100;
    printf("%d\n", x[i]);
  }
  int max = x[0];
  int min = x[0];
  for (int i = 1; i < 10; i++)
  {
    if (max < x[i]) {
      max = x[i];
    }
    if (min > x[i]) {
      min = x[i];
    }
  }
  printf("max=%d,min=%d", max, min);

}

3.数组排序

冒泡排序的基本思想

不断比较相邻的两个数,让较大的元素不断地往后移。经过一轮比较,就选出最大的数;经过第2轮比较,就选出次大的数,以此类推。对于具有N个元素的数组R[N],进行最多N-1轮比较;

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>


void main() {
    time_t ts;
    int x[10]= { 1,2,3,4,5,6,7,8,9,10 };
   /* srand((unsigned)time(&ts));
    for (int i = 0; i < 10; i++)
    {
        x[i] = rand() % 100;
        printf("%d\n", x[i]);
    }*/
    int tmp = 0;
    int count = 0;
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            if (x[i] > x[j]) {
                tmp = x[i];
                x[i] = x[j];
                x[j] = tmp;
            }
            count++;
        }
    }

    printf("count=%d\n", count);
    printf("---------------------\n");

    for (int i = 0; i < 10; i++)
    {
        printf("%d\n", x[i]);
    }

}
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>


void main() {
  time_t ts;
  int x[10] = { 1,2,3,4,5,6,7,8,9,10 };
  srand((unsigned)time(&ts));
  for (int i = 0; i < 10; i++)
  {
    x[i] = rand() % 100;
    printf("%d\n", x[i]);
  }
    
  printf("---------------------\n");
  int tmp = 0;
  int count = 0;
  for (int i = 0; i < 9; i++)
  {
    for (int j = 0; j < 9-i; j++)
    {
      printf("%d,%d\n", x[i], x[j]);
      if (x[j] < x[j+1]) {
        tmp = x[j];
        x[j] = x[j+1];
        x[j+1] = tmp;
      }
      count++;
    }
  }
  printf("count=%d\n", count);
  printf("---------------------\n");

  for (int i = 0; i < 10; i++)
  {
    printf("%d\n", x[i]);
  }
}

选择排序的基本思想

首先,选出最小的数放在第一个位置;然后,选出第二小的数放在第二个位置;以此类推,直到所有的数从小到大排序。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>


void main() {
    time_t ts;
    int x[10]= { 1,2,3,4,5,6,7,8,9,10 };
    srand((unsigned)time(&ts));
    for (int i = 0; i < 10; i++)
    {
        x[i] = rand() % 100;
        printf("%d\n", x[i]);
    }
    int count = 0;
    for (int i = 0; i < 10; i++)
    {
        int max = i;
        for (int j = i+1; j < 10; j++)
        {
            if (x[max] < x[j])
            {
                max = j;
            }
            count++;
        }
        if (i != max) {
            int tmp = x[i];
            x[i] = x[max];
            x[max]=tmp;
        }
    }

    printf("count=%d\n", count);
    printf("---------------------\n");

    for (int i = 0; i < 10; i++)
    {
        printf("%d\n", x[i]);
    }

}

插入排序的基本思想

将无序数组分为两部分,排序好的子数组和待插入的元素。在一个已经有序的小序列的基础上,一次插入一个元素,直到所有元素都加入排序好数组。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>


void main() {
    time_t ts;
    int x[10]= { 1,2,3,4,5,6,7,8,9,10 };
    srand((unsigned)time(&ts));
    for (int i = 0; i < 10; i++)
    {
        x[i] = rand() % 100;
        printf("%d\n", x[i]);
    }
    int count = 0;
    int tmp = 0;
    int pos = 0;
    for (int i = 1; i < 10; i++)
    {
        tmp = x[i];
        pos = i - 1;
        while ((pos>=0) && (tmp>x[pos]))
        {
            x[pos + 1] = x[pos];
            pos--;
            count++;
        }
        x[pos + 1] = tmp;
    }

    printf("count=%d\n", count);
    printf("---------------------\n");

    for (int i = 0; i < 10; i++)
    {
        printf("%d\n", x[i]);
    }

}

4.二维数组

二维数组在概念上是二维的,有行和列,但在内存中所有的数组元素都是连续排列的,它们之间没有“缝隙”。以下面的二维数组 a 为例:

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

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

int a[3][4] = {0};

10.C语言- 数组 (https://mushiming.com/) 技术博客 第6张

从概念上理解,a 的分布像一个矩阵:

\left( %左括号 \begin{matrix} %该矩阵一共3列,每一列都居中放置 0& 1 & 2& 3\\ %第一行元素 4& 5& 6 &7\\ %第二行元素 8& 9& 10 &11\\ %第二行元素 \end{matrix} \right) %右括号

但在内存中,a 的分布是一维线性的,整个数组占用一块连续的内存:

10.C语言- 数组 (https://mushiming.com/) 技术博客 第7张

C语言中的二维数组是按行排列的,也就是先存放 a[0] 行,再存放 a[1] 行,最后存放 a[2] 行;每行中的 4 个元素也是依次存放。数组 a 为 int 类型,每个元素占用 4 个字节,整个数组共占用 4×(3×4) = 48 个字节。

数组赋值

void main() {
  int a[3][4];
  for (int i = 0; i < 3; i++)
  {
    for (int j = 0;  j < 4;  j++)
    {
      a[i][j] = (i+1) * (j+1);
      printf("%-3d", a[i][j]);
    }
    printf("\n");
  }
}

10.C语言- 数组 (https://mushiming.com/) 技术博客 第8张

void main() {
  int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };

  printf("%p", &a);

  system("pause");
}
10.C语言- 数组 (https://mushiming.com/) 技术博客 第9张

void main() {
  int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };

  printf("%p", &a);

  for (int i = 0; i < 12; i++)
  {
    a[i / 4][i % 4] = i+1;//3行4列
  }

  system("pause");
}
10.C语言- 数组 (https://mushiming.com/) 技术博客 第10张

void main() {
  int num[2][3] = { {1},{2} };
  printf("%p", &num);
  system("pause");
}
10.C语言- 数组 (https://mushiming.com/) 技术博客 第11张

访问元素

void main() {

  int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };
  int val = a[2][3];
  printf("val=%d", val);
}
void main() {

  int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };
  for (int i = 0; i < 3; i++)
  {
    for (int j = 0; j < 4; j++)
    {
      printf("%d行%d列=%d ", i, j, a[i][j]);
    }
    printf("\n");
  }
}

地址

行地址对应就是每行第一个元素地址

void main() {
  
  int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };

  printf("%p,%p,%p", &a[0], &a[1], &a[2]);
  system("pause");
}
10.C语言- 数组 (https://mushiming.com/) 技术博客 第12张

打印一个二维数组

#include<stdio.h>
#include<stdlib.h>

#define N 10

void main() {
  int num[N][N];
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < N; j++)
    {
      num[i][j] = N * i + j + 1;
      printf("%-5d", num[i][j]);
    }
    printf("\n");
  }
}
#include<stdio.h>
#include<stdlib.h>

#define N 10

void main() {
  int num[N][N];
  int a = 0;
  for (int i = 0; i < N*N; i++)
  {
    num[i % N][i % N] = ++a;
    printf("%-5d", num[i % N][i % N]);
    if ((i+1) % N == 0) {
      printf("\n");
    }
  }
}
10.C语言- 数组 (https://mushiming.com/) 技术博客 第13张

数组转置

#include<stdio.h>
#include<stdlib.h>

void main() {
  int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
  for (int i = 0; i < 3; i++)
  {
    for (int j = 0; j < 4; j++)
    {
      printf("%-5d", a[i][j]);
    }
    printf("\n");
  }

  int b[4][3];
  for (int i = 0; i < 4; i++)
  {
    for (int j = 0; j < 3; j++)
    {
      b[i][j] = a[j][i];
      printf("%-5d", b[i][j]);
    }
    printf("\n");
  }
}

这个在图形上用的比较多

5.三维数组

如果数组是N维,就需要N个下标来访问数组中的元素,同理,在声明高维数组时,除了和一维二维数组声明一样要制定元素类型和数组名外,还要指定每一维的大小,以帮助编译器确定到底要分配多大的内存块。

#include<stdio.h>
#include<stdlib.h>

void main() {
  int num[2][3][4];
  printf("%d\n", sizeof(num));
  int x = 0;
  for (int i = 0; i < 2; i++)
  {
    for (int j = 0; j < 3; j++)
    {
      for (int z = 0; z < 4; z++)
      {
        num[i][j][z] = ++x;
        printf("%-5d", num[i][j][z]);
      }
      printf("\n");
    }
    printf("\n");
  }
}
10.C语言- 数组 (https://mushiming.com/) 技术博客 第14张

6.几个例子

打印一个杨辉三角型

10.C语言- 数组 (https://mushiming.com/) 技术博客 第15张

我们定义一个二维数组,所有元素先初始化为0

给数组的第1列和对角线元素赋值为1

其余元素a[i][j]=a[i-1][j-1]+a[i-1][j]

输出这个二维数组的下三角

#include<stdio.h>
#include<stdlib.h>

#define N 10
void main() {
    int a[N][N] = { 0 };
  for (int i = 0; i < 10; i++)
  {
    for (int j = 0; j <= i; j++)
    {
      //第一列和对角线也改成1
      if (j == 0 || i == j) {
        a[i][j] = 1;
      }
      else {
        a[i][j] = a[i - 1][j - 1]+a[i-1][j];
      }
      printf("%5d",a[i][j]);
;    }
    printf("\n");
  }
  printf("\n");
  for (int i = 0; i < 10; i++)
  {
    printf("%*d", 20 - i * 2, a[i][0]);
    for (int j = 1; j <= i; j++)
    {
      printf("%5d", a[i][j]);
    }
    printf("\n");
  }
}
10.C语言- 数组 (https://mushiming.com/) 技术博客 第16张

二分查找法

标准查询

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

void main() {
    time_t ts;
    unsigned int num = time(&ts);//取得时间,转换整数
    srand(num);
    int a[10];
    for (int i = 0; i < 10; i++)
    {
        a[i] = rand() % 20;
        printf("%d\n", a[i]);
    }
    for (int i = 0; i < 10; i++)
    {
        if (a[i] == 10) {
            printf("找到数字:%d",i);
            break;
        }
    }
}

二分法,也称为折半查找法,是一种适用于大量数据查找的方法,但是要求数据必须的排好序的,每次以中间的值进行比较,根据比较的结果可以直接舍去一半的值,直至全部找完(可能会找不到)或者找到数据为止。

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

void main() {
    int a[100];
    for (int i = 0; i < 100; i++)
    {
        a[i] =i;
        printf("%d\n", a[i]);
    }
    int find = 40;
    //每次比较中间数
    int min = 0;
    int max = 99;
    int mid = 0;
    while (min<max)
    {
        printf("min:%d,max:%d,mid:%d\n", min, max, mid);
        mid = (min + max) / 2;
        if (find == a[mid]) {
            printf("找到了");
            break;
        }
        else {
            if (find < a[mid]) {
                max = mid - 1;
            }
            else {
                min = mid+1;
            }
        }
    }
}
THE END

发表回复