C语言学习记录(五)

C语言学习记录(五)

一、知识要点(数组)

1、一维数组

  • 一维数组的定义

    • 数组是由一些相同类型的数据组成的有序集合,每个数组都有一个数组名,数组中的一个数据称为一个数组元素。其中下标可以指明一个数组元素的位置。数组可以是多维的。
    • 一维数组只有一个下标,定义一维数组的格式为类型标识符 数组名[常量表达式];
    • 类型标识符是数组中每一个元素的数据类型,比如int,float,char。
    • 数组名就是所定义的数组的名字,其命名规则要遵循c语言标准。
    • 方括号内的常量表达式是数组的元素个数,也称数组长度。该表达式不能是变量。
    • C语言编译系统为数组在内存中分配了一片连续的储存单元,下标小的元素分配的单位地址低,下标大的元素单位地址高
    • C语言规定首个元素的下标为0.假如int a[5],那么它的五个元素为a[0],a[1],a[2],a[3],a[4]。
  • 一维数组的初始化

    • 给数组指定初值,就是初始化。语法格式为:类型标识符 数组名[常量表达式]={初值列表}

    • 定义数组时对所有数组元素赋予初值

      • 例如int a[10] = {0,1,2,3,4,5,56,5,3,9}
      • 系统将按初值的顺序排序,依次给数组元素赋值。初始化后数组a中个元素的值为a[0]=0,a[1]=1,a[3]=3……
    • 对部分数组元素赋初值

      • 例如int a[10]={0,1,-2};
      • 如果只有3个初值,那么只把这三个初值赋给前三个元素,后面七个直接补零。
    • 对所有元素赋初值时,可以不用写括号中括号内的数,c语言编译系统直接根据你写的值确定长度。

      • #include<stdio.h>//一维数组初始化几种方法比较
        int main()
        {
        	int a[5] = { 4,6,9,0,12 };
        	int b[5] = { 1,5 };
        	int c[5], i;
        	printf("数组a:");
        	for (i = 0;i < 5;i++)
        		printf("%6d", a[i]);
        	printf("\n数组b: ");
        	for (i = 0;i < 5;i++)
        		printf("%6d", b[i]);
        	printf("\n数组c: ");
        	for (i = 0;i < 5;i++)
        		printf("%6d", c[i]);
        	return 0;
        }
        
      • 数组c未被初始化,所以输出的值是原本就存在单位地址上的数据。

  • 一维数组元素的引用

    • 数组属于构造类型,数组名实质上代表了数组在内存中的起始地址,是一个常量地址。引用过程中不能对数组名进行赋值,也不能直接引用数组名来引用整个数组,只能逐个引用单个数组元素。

    • 引用格式为:数组名[下标]。注意:int a[5]括号中的五是常量表达式,指的是数组长度,而a[3]指的是数组中第四个元素。

    • #include<stdio.h>//一维数组元素的赋值与输出
      int main()
      {
      	int a[5], i;
      	for (i = 0;i < 5;i++)
      		a[i] = i + 1;
      	for (i = 0;i < 5;i++)
      		printf("%3d", a[i]);
      	return 0;
      }
      
    • 边界问题:C语言编译时不会检查数组元素下标是否出界,而是会把数组内存地址下面的单元地址赋给数组。如果把握好数组的使用,可能会造成不可预料的后果。

2、二维数组

  • 二维数组的定义

    • 二维数组是指数组元素有两个下标的数组,定义语法格式为:类型标识符 数组名[常量表达式1][常量表达式2】;其中常量表达式1代表了数组的行数,常量表达式2代表了数组的列数。比如int a[4][6]就是定义一个有四行六列的二位整形数组。

    • 二维数组的数组元素表达和引用格式语法:数组名[下标1][下标2】。如a[3] [2]指的是a数组中第四行,第三列的数组元素。

    • 从储存上看二维数组仍然是一位线性空间,每个元素在内存中的存放是按按行优先顺序进行的,即先存放第一行,然后第二行……。

    • 有二维数组的定义,就可以类推出多维数组。但是他们其实都是二维数组,只不过前面多加了几个量级。

  • 二维数组的初始化

    • 二维数组的初始化与一维数组类似。初始值应按照顺序写在花括号内,各初值用逗号隔开:int a[2][3] = {14,23,6,32,6,4};,但这种方法当数据过多的时候容易造成纰漏。
    • 二维数组可采用分行形式对各元素赋值。例如int a[3][4] = {{5,4,2,4},{23,-3,4,-23},{231,43,34-345}};这种方法直观且不容易出错。
    • 部分元素赋值
      • 按顺序给二维数组赋值时,如果只对前面部分赋值,那么其他未被赋值的地方会自动补零。
      • 当分行形式赋值时,对每行前面一部分元素赋值,那么后面未被赋值的元素自动补零。
    • 二维数组的初始化可省略行长度,但不能省略列长度。
      • 顺序赋值省略行长度时,系统自动根据初始值数目与第二维大小的比来确定第一维大小。
      • 分行时就采用括号数来确定行数。
  • 二维数组元素的引用

    • 与一维数组一样,二维数组也不能引用整个数组,只能单个。程序编写时常采用二层循环结构实现对二维数组各个元素的引用。

    • #include<stdio.h>//二维数组元素的赋值与输出
      int main()
      {
      	int a[3][4], i, j;
      	for (i = 0;i < 3;i++)//外层循环控制行
      		for (j = 0;j < 4;j++)//内层循环控制列
      			scanf("%d", &a[i][j]);
      	printf("\n数组是:");
      	for (i = 0;i < 3;i++)
      		for (j = 0;j < 4;j++)
      			printf("%3d", a[i][j]);
      	return 0;
      }
      
    • #include<stdio.h>//有程序产生某个数组a
      int main()
      {
      	int a[3][5], i, j;
      	for (i = 0;i < 3;i++)
      		for (j = 0;j < 5;j++)
      			a[i][j] = i * 5 + j + 1;
      	printf("数组a为:");
      	for (i = 0;i < 3;i++)
      		for (j = 0;j < 5;j++)
      			printf("%6d", a[i][j]);
      	return 0;
      }                                                                                   
      

3、数组与循环计算

  • 数组元素的查找与删除

    • ///在数组中按顺序查找数据:把数组首个元素与与变量x相比较,相同则记住下标,否则就继续往后找
      #include<stdio.h>
      #include<math.h>
      int main()
      {
      	int a[15];
      	int i,j,b;
      	for (i = 0, j = 1;i < 15;i++, j++)//创建一组数据
      	{
      		a[i] = j;
      	}
      	int x;
      	scanf("%d", &x);
      	for (i = 0;i < 15;i++)
      	{
      		if (a[i] == x)//按序查找
      		{
      			printf("是第%d个元素",i+1);
      			b=1;//表示查找成功
      			break;
      		}
      	}
      	if (b != 1)
      		printf("未查找到相关数据。");
      	return 0;
      }
      
    • 折半查找法:效率比按序查找法高,不过前提是数组已经排列好了。首先找到数组中间的数,然后根x进行比较,如果等于x,那么求取出来;如果大于x,那么就在左半部分再找到中间的数与x想比较,一直循环下去;如果小于x,则就找右半部分中间的数。

      • #include<stdio.h>
        #include<math.h>
        int main()
        {
        	int a[15],i,j=1;
        	for (i = 0;i < 15;i++,j+=2)//创建一个数组
        	{
        		a[i] = j;
        	}
        	int p = 0, left = 0, right = 14, x,mid;
        	scanf("%d", &x);
        	for (p = 0;left <= right;)//折半查找法
        	{
        		mid = (left + right) / 2;
        		if (a[mid] == x)
        		{
        			printf("为第%d个数组元素。",mid+1);
        			p = 1;
        			break;
        		}
        		else if (a[mid] < x)
        			left = mid + 1;
        		else
        			right = mid - 1;
        	}
        	if (p == 0)
        		printf("未找到相关数据。");
        	return 0;
        }
        
    • 删除指定位置的数

      • 要实现删除,可以让后面的数覆盖前面的数,不过数组大小会减一。

      • #include<stdio.h>
        #include<math.h>
        int main()
        {
        	int a[15],i,j=1;
        	for (i = 0;i < 15;i++,j+=2)//创建数组
        	{
        		a[i] = j;
        	}
        	int x;
        	scanf("%d", &x);
        	for (i = x;i < 14;i++)//核心算法
        	{
        		a[i] = a[i + 1];
        	}
        	for (i = 0;i < 15;i++)//打印数组
        		printf("%d\t", a[i]);
        	return 0;
        }
        
    • 将数组右移,移动次数由键盘决定

      • 可以先将每个元素向前移一位,然后重复想要的次数。第一位移到最后一位,可以让t做中间数。

      • #include<stdio.h>
        #include<math.h>
        int main()
        {
        	int a[15],i,j=1;
        	for (i = 0;i < 15;i++,j+=2)//创建数组
        	{
        		a[i] = j;
        	}
        	int x,k,t;
        	scanf("%d", &x);
        	for (k = 1;k <= x;k++)//外层控制移动次数
        	{
        		t = a[0];
        		for (i = 0;i < 14;i++)//核心算法
        		{
        			a[i] = a[i + 1];
        		}
        		a[14] = t;
        	}
        	for (i = 0;i < 15;i++)//输出数组
        		printf("%d\t", a[i]);
        	return 0;
        }
        
  • 数组的排序与矩阵转置

    • 利用冒泡法对数组进行排序

      • 基本思想:设有十五个数据存放在一维数组,第一轮冒泡: 首先比较a[0]和a[1]两个元素值,若a[0]>a[1],则两者交换,否则不叫换,接着比较a[1]和a[2]……直到最大的数沉底,然后开启第二轮冒泡……

      • #include<stdio.h>//利用冒泡算法对数组进行从小到大排序
        #include<math.h>
        int main()
        {
        	int a[15],i,j=1;
        	for (i = 0;i < 15;i++,j-=2)
        	{
        		a[i] = j;
        	}
        	int k,t,m;
        	for (m = 14;m > 0;m--)//多轮冒泡
        	{
        		k = m;
        		for (i = 0;i < k;i++)//一轮冒泡
        		{
        			if (a[i] > a[i + 1])//交换数据
        			{
        				t = a[i];
        				a[i] = a[i + 1];
        				a[i + 1] = t;
        			}
        		}
        	}
        	for (i = 0;i < 15;i++)
        	{
        		printf("%d\t", a[i]);
        	}
        	return 0;
        }
        
    • 选择排序法

      • 基本思想:从数组中选个最大数,然后放在数组最前面,在从后面选个最大数放到第二位,如此循环。

      • #include<stdio.h>//利用选择排序法对数组进行从小到大排序
        #include<math.h>
        int main()
        {
        	int a[15],i,j=1;
        	for (i = 0;i < 15;i++,j-=2)
        	{
        		a[i] = j;
        	}
        	int m, t, max;
        	for (m = 0;m < 14;m++)//多轮交换
        	{
        		max=m;
        		for (i = m + 1;i < 15;i++)//选择数组中最大数
        		{
        			if (a[max] < a[i])
        				max=i;
        		}
        		if (max=i)//将max与i交换
        		{
        			t = a[i];
        			a[i] = a[max];
        			a[max] = t;
        		}
        	}
        	for (i = 0;i < 15;i++)
        	{
        		printf("%d\t", a[i]);
        	}
        	return 0;
        }
        
    • 组合重排

      • 基本思想:将两个已排好序(升序)a,b的数组存放在空数组c中。首先把a,b的第一个数拿来比较,然后小的放在c中第一个元素里,大的再跟小的后面的元素比大小,重复如此。最后把比完大小还剩下的数据放在c数组的末尾。

      • #include<stdio.h>//对已经排好序(升序)的两个数组合并重排
        #include<math.h>
        int main()
        {
        	int a[5], b[7], c[12];
        	int i, j, k, m, n, o;
        	for (i = 0,j=2;i < 5;i++,j++)//创建数组a
        	{
        		a[i] = 3*j;
        	}
        	for (k = 0, m = -5;k < 7;k++,m+=3)//创建数组b
        	{
        		b[k] = m;
        	}
        	i = k = n = 0;
        	while (i <=4 && k <= 6)
        	{
        		if (a[i] <= b[k])//判断a,b大小,然后小的存到c中
        		{
        			c[n] = a[i];
        			n++;
        			i++;
        		}
        		else
        		{
        			c[n] = b[k];
        			n++;
        			k++;
        		}
        	}
        	if (i <= 4)//判断哪个数组剩余数据,然后补到c后面
        	{
        		for (o = i;o <= 4;o++)
        		{
        			c[n] = a[o];
        			n++;
        		}
        	}
        	else
        	{
        		for (o = k;o <= 6;o++)
        		{
        			c[n] = b[o];
        			n++;
        		}
        	}
        	for (n = 0;n < 12;n++)//打印数组c
        		printf("%d\t", c[n]);
        	return 0;
        }
        
    • 判断二维数组是否为对称矩阵

      • 算法:对称矩阵的定义是二维数组中所有第i行j列的元素值均等于第j行i列的元素。

      • #include<stdio.h>//判断二维数组是否为对称矩阵
        #define N 4
        int main()
        {
        	int a[N][N];
        	int i, j, flag = 1;
        	printf("请输入十二个整数:\n");
        	for (i = 0;i < N;i++)
        	{
        		for (j = 0;j < N;j++)
        		{
        			scanf("%d", &a[i][j]);
        		}
        	}
        	for (i = 0;i < N && flag;i++)
        	{
        		for(j=0;j<i;j++)
        			if (a[i][j] != a[j][i])
        			{
        				flag = 0;
        				break;
        		}
        	}
        	if (flag == 1)
        		printf("Array a is yes!\n");
        	else
        		printf("Array a is no!\n");
        	return 0;
        }
        

2、学习心得

数组这一章数据类型啥的简单,但是这些排序算法还得多练,有点力不从心了

posted on 2023-03-10 20:20  嗷呜ニャー~  阅读(135)  评论(0编辑  收藏  举报