6.C语言数组

本文详细介绍了C语言中的数组,包括一维数组和二维数组的定义、初始化、内存分布、元素引用和操作。讲解了数组的长度、字符串长度与数组大小的区别,并通过实例展示了数组的排序算法(冒泡、选择、插入、随机)、查找、求和、最大值、最小值等操作。此外,还探讨了多维数组的内存分布和相关题目解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数组

int a0,a1; -> 这个东西是不能通过循环去引用的,名字是不能拆分的,所有C语言中引入了数组

一、数组定义:

​ 数组是指一组具有相同类型的数据(变量)的集合
​ int a0,a1…a99; ->如果是用数组定义 —>a[100] 就代表着100个整型数据

二、一维数组

定义的格式

​ 本来->变量的类型[变量的个数] 变量的名字; -> int[10] a;
​ 但是 ->在c语言里面没有int[10]这么一个类型 -> 因此这个[10]就只能放后面
​ 所以数组的定义就是 ->变量的类型 变量的名字[变量的个数]; -> int a[10];

相关要求:

​ 变量的类型:c语言里面合法的类型都可以,如基本类型、构造类型

​ 变量的名字:符合c语言的命名规则就可以了

​ 变量的个数:老版的编译器这个里面只能是常量表达式,发展到现在我们可以用一个有确定值的变量来给这给 个数

​ 注意:如果你是用变量去定义的数组,你是不能初始化的

​ 例子:

	int a[5];
	//意思就是有5个相同int的变量被定义出来了
	//你要用这5个变量  直接用这个a就可以了
	//typeof -> 求一个变量的类型
	//typeof(a) -> int[5]
	int * p = a;
	//typeof(p) -> int *
	//int[5] int*在很大意义上面是一样的,但是也不一样 int*没有范围,int[5]是确定了范围

数组初始化:

  1. 数组定义完之后我们对其全部初始化
int a[5] = {1,2,3,4,5};			//一定不要超标
char name[10] = "abcdefghi";	//字符串后面必有\0

如果我想对这个数组全部初始化,定义数组的时候可以不用给个数,编译器可以猜多少个元素

int a[] = {1,2,3,4,5};
//与int a[5] = {1,2,3,4,5};一模一样
  1. 数组可以部分初始化,后面没有初始化的部分会全部初始化为0
int a[5] = {1,2,3}; // a[3] == 0 , a[4] == 0

3.数组不初始化里面的值是未知的,很多时候我们可以对一个数组进行清零

	int a[5] = {0};
*注意:

​ int a[5] = {0};

​ 只有在定义的时候 也就是初始化的时候才能这么干
​ 经过不知名的操作之后, 这个a里面就有了各种各样的值
​ 这个时候我又想对这个数组清零

​ ---->只能循环

​ memset ->实际上也是用循环来实现的

数组在内存中的存放:

​ 引言:

​ 数组定义出来了,要想使用,我们还需要知道这个数组的地址,也就是这几个数据在内存里面的存放

​ 数组的内存分布:

​ 数组定义之后 ,里面的每个元素是在连续的地址空间里面,第2个紧挨着第一个存放就可以了

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p5oqTtGf-1625710547555)(E:\粤嵌学习笔记\C语言\数组的存放.png)]

一维数组元素的引用:

用数组的下标去引用这个数组
数组名[下标]; 下标从0开始 ,小于数组的个数
示例:
int a[10];
a[0] ->数组的第一个元素
a[1] ->数组的第二个元素

a[9] ->数组的第十个元素,也就是最后一个

一维数组元素的使用:

​ 数组元素用的时候跟一个变量是一模一样的,变量怎么用那么数组的元素就怎么用
​ 示例:

				int b;
				b = 1024;
				int a[10];
				a[0] = 1024;
				a[9] = 1025;

​ 跟普通变量一样 , 符合左值与右值的规则,因此数组的元素一样的是可以取地址的

题目:打印数组

​ 定义一个数组 手动输入里面的值 用循环,并打印出这个数组

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

数组名的含义:

​ 例:
​ int a[10]; 变量的个数 ->代表着相同类的数据的个数
​ a有两个含义:

​ 1.数组首地址,这个时候相当于一个指针,指向数组首地址

​ 2.变量 ,代表整个数组

int main()
{
    int a[10];
    int *p = a;
    sizeof(a);			//40,因为a就是一个变量,代表整个数组。sizeof(a) -> sizeof(int[10])
	sizeof(p);    		//4/8 
}
//sizeof(数组名):返回数组所有元素占有的内存空间字节数。

//sizeof(指针)  :返回计算机系统的地址字节数,如果是32位系统,返回4,64位系统返回8

int a[10];
scanf("%d",&a); //不可以
//typeof(a) -> int[10]
//typeof(&a) -> typeof(&int[10]) -> int[10] * -> int **
//	表明&a是整个数组的地址,整个数组的地址是代表的整个数组
//	而数组的首地址代表数组第一个元素
	a + 1 		// 代表的是第二个元素
	&a + 1 		// 代表跳过这个数组
    ++a;		//不可以,a本身不能变
	scanf("%d",a);  a -> &a[0]
	这么写是可以的  a代表的就是第一个元素 并且它就是一个地址
*重点注意:

​ a代表的是首地址 , 同时也是代表的第一个元素的地址
​ 因此左值右值都可以
​ * a = 1024; <-> a[0] = 1024
​ ++a,a++是不行的
​ a + 1是可以的
​ 核心思维:虽说a是个首地址 并且a代表的是第一个元素的地址
​ 并且a本身就是一个变量
​ 但是a由于代表的是整个地址 如果你改变了那么这个数组就变了
​ 因此a是不能改变的
​ 因此 a =a + 1也不行

#include<stdio.h>
int main()
{
   char a[5]={'A','B','C','D'};
   char (*p3)[10] = &a;
   char *p4 = a;
   printf("%p\n",p3);
   printf("%p\n",p3+1);
   printf("%p\n",p4);
   printf("%p\n",p4+1);
   return 0;
}
/*运行结果:
0x7ffe10adcd23
0x7ffe10adcd2d
0x7ffe10adcd23
0x7ffe10adcd24
*/
/*
a:代表数组首个元素的地址
&a:代表整个数值的首地址
值是相同的,但意义不同
*/

三、字符串的长度(strlen)和数组的大小(sizeof)

数组里面有一个比较特殊的存在 ,字符串数组,这个里面涉及两个概念,字符串长度和数组的大小

字符串长度不等于字符串数组大小

字符串数组所能容纳下的的最长的字符串长度为 = 字符串数组大小 - 1
因为还有一个字节需要用来存放“\0”

//例1:
char name[16] = "penglei";
printf("%d\n",sizeof(name));	//求数组大小,输出16,表示数组大小为16字节
printf("%d\n",strlen(name));	//求字符串长度,遇到\0结束,输出结果为7
			
char name[] = "penglei\0henshuai";
printf("%d\n",sizeof(name));	//求数组大小,输出17,字符串末尾一定是以\0结尾
printf("%d\n",strlen(name));	//求字符串长度,遇到\0结束,输出结果为7

数组在分配空间的时候不是看谁先定义的
是看谁小一些 , 谁就在前面 , 并且连续开辟
%s 和strlen都是需要看到\0才会结束的

//例2:
	int i;
	char name[3] = {'a','b','c'};
	printf("%d\n",sizeof(name));	//求数组大小,输出3,表示数组大小为3字节
	printf("%d\n",strlen(name));	//结果未知,数组后面是多少都不知道,不知道什么时候能遇到\0结束
				
	char name[3];
	char name1[10];
	for(i=0;i<7;i++)
	{
		scanf("%c",&name[i]); //-> {'a','b','c','d','e','f','g'}
	}
	name1[0] = 'h';
	printf("%s\n",name);	// 输出结果->abc
	printf("%s\n",name1);	//输出结果->hefg

注意:
以下代码虽说有一定的问题, 但是里面说明了很多的问题

#include <stdio.h>
#include <string.h>

//这个代码实质是有问题的 写到这里只是为了说明数组存放、越界等问题
int main()
{
	char name1[10] = {0};
	char name[2] = {0};
	char name2[3] = {0};
	int i = 0;
	for(;i < 7;i++)//你已经越界了
	{
		scanf("%c",&name[i]); //-> {'a','b','c','d','e','f','g'}
	}
	
	name1[0] = 'h';	
	/*name1 = "h"; c语言里面字符串是不能直接赋值的,我们想要赋值字符串 只能一个字节一个字节的赋值
		只有在初始化的时候才能直接等于*/


	char * p;
	p = "hehe"; //这个hehe会放入一个叫.rodata的空间
			//放入这个空间之后  返回一个首地址给p
	
	
	
	printf("%d  %s\n",(int)strlen(name),name); //这里也有越界
	printf("%d  %s\n",(int)strlen(name1),name1);
	printf("%d  %s\n",(int)strlen(name2),name2);
	printf("%s\n",p);
	return 0;
}

四、一维数组相关题目

题目:求数组和、最大值、最小值

1.求一个数组的和,并且打印出最大的与最小的

//求一个数组的和,并打印出这个数组中的最大最小值
#include<stdio.h>
int main()
{
	int a[5]={3,2,6,1,7};
	int sum = 0,i,max = a[0],min = a[0];
	for(i = 0;i<5;i++)
	{
		if(max<a[i])
		{
			max = a[i];
		}
		if(min>a[i])
		{
			min = a[i];
		}
		sum += a[i];
	}
	printf("sum = %d\n",sum);
	printf("最大值为:%d,最小值为:%d\n",max,min);
	return 0;
}


题目:打印斐波拉契数列

2.斐波拉契数列,打印前20项和前20项的和
1 1 2 3 5 8 13 … 即后一项等于前两项之和

//斐波拉契数列,打印前20项和前20项的和
#include<stdio.h>
int main()
{
	int i,j,sum = 2;
	int a[20] = {1,1};
	for(i = 2;i < 20;i++)
	{
		a[i] = a[i-1] + a[i-2];
		sum += a[i];
	}
	for(j = 0;j < 20;j++)
	{
		printf("%d\t",a[j]);
	}
	printf("\nsum = %d\n",sum);
	return 0;
}

题目:判断数列是否递增

3 .给定一个数列,判断这个数列是否为递增, 如果是 打印yes 否则打印no

//给定一个数列,判断这个数列是否为递增,是的话打印yes,否则打印no
#include<stdio.h>
int main()
{
	int i;
	int a[6] = {2,3,4,5,6,7};
	for(i = 0;i < 5;i++)
	{
		if(a[i]>a[i+1])
		{
			printf("no\n");
			break;
		}
	}
	if(i == 5)
		printf("yes\n");
	return 0;
}
/*
错误点:for(i = 0;i < 6;i++)
for循环里面的判断条件应该是i < 5,而不是i < 6,
要考虑到a[i+1]不能越界。
*/
/*老师代码:不用break;直接用return 0;结束主函数。
	int i;
	int a[6] = {2,3,4,5,6,7};
	for(i = 0;i < 5;i++)
	{
		if(a[i]>a[i+1])
		{
			printf("no\n");
			return 0;
		}
	}
	printf("yes\n");
*/

题目:有序数列查找元素

4.给定一个有序的数列,查找其中的一个元素
​ 1 遍历 -> 一个个找
​ 2 二分法 -> 折中查找

//给定一个有序数列,查找其中一个元素
//方法1:遍历 -> 一个个找
#include<stdio.h>
int main()
{
	int i,n;
	int a[6] = {1,2,5,7,8,9};
	printf("请输入想要查找的元素:");
	scanf("%d",&n);
	for(i = 0;i < 6;i++)
	{
		if(n == a[i])
		{
			printf("a[%d]=%d\n",i,n);
			return 0;
		}
	}
	printf("没有找到该元素!\n");
}

//方法2:二分法 -> 折中查找
#include<stdio.h>
int main()
{
	int a[6]={1,2,5,7,8,9};
	int left = 0,right = 5,mid,n;
	printf("请输入想要查找的元素:");
	scanf("%d",&n);
	while(1)
	{
		mid = (left+right)/2;
		if((right == left + 1)||(right == left))
		{
			if(n == a[left])
			{
				printf("a[%d] = %d\n",left,n);
				return 0;
			}
			else if(n == a[right])
			{
				printf("a[%d] = %d\n",right,n);
				return 0;
			}
			else
				{
					printf("查询无果!\n");
					return 0;
				}
		}
		if(n == a[mid])
		{
			printf("a[%d] = %d\n",mid,n);
			return 0;
		}
		if(n > a[mid])
		{
			left = mid + 1;
		}
		if(n < a[mid])
		{
			right = mid - 1;
		}
	}
}

题目:冒泡排序

冒泡 -> 一趟冒泡会将最大值移到最后
​只要前面的一个值比后面的一个值大 ,那么就换位置

//冒泡排序
#include<stdio.h>
int main()
{
	int a[10]={2,5,2,5,32,4,6,9,66,1};
	int i,j,k;
	for(i = 0;i<9;i++)
	{
		for(j = i+1;j<10;j++)
		{
			if(a[i]>a[j])
			{
				a[i] = a[i]^a[j];
				a[j] = a[i]^a[j];
				a[i] = a[i]^a[j];
			}
		}
	}
	for(k = 0;k<10;k++)
	{
		printf("%d\t",a[k]);
	}
	printf("\n");
	return 0;
}

题目:选择排序

选择排序 -> 一趟找出没有排好的最大值 , 放到没有排好的最后面去
我们需要将最大值的下标保存下来

//选择排序:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置(末尾位置),然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾(开头)。
//选择排序跑一趟只交换一次位置,和冒泡排序不同的地方是冒泡排序是边比边交换
#include<stdio.h>
int main()
{
	int a[10]={2,5,2,5,32,4,6,9,66,1};
	int i,j,k,max = 0;		//max标记无序序列最大值下标
	for(i = 9;i>0;i--)
	{
		for(j = 0;j<=i;j++)
		{
			if(a[max]<a[j])
				max = j;
		}
		a[max] = a[max]^a[i];
		a[i] = a[max]^a[i];
		a[max] = a[max]^a[i];
	}
	for(k = 0;k<10;k++)
	{
		printf("%d\t",a[k]);
	}
	printf("\n");
	return 0;
}

题目:插入排序

//插入排序:将一个记录插入到已经排好序的有序表中,
//从而形成一个新的、记录数增1的有序表。
//初始时已排好的序列为a[0]一个数,a[1]和a[0]比较,大不变,小,交换位置。

#include<stdio.h>
int main()
{
	int i,j,k,num;
	int a[6]={5};
	printf("请输入5个数:");
	for(i = 1;i<6;i++)			//外循环,循环插入5个数
	{
		scanf("%d",&a[i]);
		for(j = 0;j<i;j++)		//内循环,对插入的数排位置
		{
			if(a[i]<a[j])
			{
				//移位
				num = a[i];
				k = i;
				while (k >= j+1)
				{
					a[k] = a[k-1];
					--k;
				}
				a[j] = num;
				break;
			}
		}
	}
	for(k=0;k<6;k++)
	{
		printf("%d\t",a[k]);
	}
	printf("\n");
	return 0;
}

题目:随机排序

需将 1 ~ 100 随机的分布到100个元素的数组里面去,且数组里面的数是不会重复的

//	需求  1 ~ 100 随机的分布到100个元素的数组里面去
//	数组里面的数是不会重复的
/*	代码思想:将1~100随机插入到arr[100]中,add[100]记录下
	arr[100]中0的下标,即未被插入数字的空位下标*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
	int i,j,k,num = 100;		//num:剩余0(空位)的个数
	int arr[100]={0};
	int add[100]={0};
	srand((int)time(NULL));
	for(i = 1;i<=100;i++)		//循环将1~100随机插入arr[100]中
	{
		
		arr[add[rand()%num]] = i;	//随机位置插入i
		--num;
		for(j = 0,k = 0;k<100;k++)	//插完一个数后,遍历arr[100]更新add[100]
		{
			if(0 == arr[k])
			{
				add[j] = k;
				j++;
			}
		}
	}
	for(i = 0;i<100;i++)
	{
		printf("%d\t",arr[i]);
	}
	printf("\n");
	return 0;
}
//需求  1 ~ 100 随机的分布到100个元素的数组里面去
//数组里面的数是不会重复的
/*代码思想:先将1~100按顺序插入数组arr[100]中,
再将每一个数与下标为1~99的随机一个数交换*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
	int i,j,temp;
	int arr[100]={0};
	srand((int)time(NULL));
	for(i = 1;i<=100;i++)
	{
		arr[i-1] = i;
	}
	for(i = 99;i>=0;i--)
	{
		j = rand()%100;
		temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}
	for(i = 0;i<100;i++)
	{
		printf("%d\t",arr[i]);
	}
	printf("\n");
}
/*测试结果:
随机交换位置后出现数字0
原因:源代码
		arr[i] = arr[i]^arr[j];
		arr[j] = arr[i]^arr[j];
		arr[i] = arr[i]^arr[j];
存在问题:
		i有可能等于j,相等就会出现
		a[i]=a[i]^a[i] -> a[i] = 0;
		a[j]=a[j]^a[j] -> a[j] = 0;
		a[i]=0^0 -> a[i] = 0;
		设a[i]的值是6,6^6 等于0
		a[i]原有的值就丢失了,变成0了
考虑那种更公平:
	(1)将每一个数与下标为0~99,包括它自己本身的值进行随机交换
	(2)从最后一个数开始,每一个数与除自己本身的前面的数进行随机交换位置
*/

题目:找数组中第二大的值

//找一个数组中的第二大的值
//更新最大值的同时将没有更新之前的最大值换到第二大就可以了
//如果有一个值比第二大的大 但是比第一大的小 那么直接更新第二大的
#include<stdio.h>
int main()
{
	int a[5]={3,5,8,6,4};
	int i,max=a[0],max2=a[0];
	for(i=1;i<5;i++)
	{
		if(max2<a[i])
		{
			if(max<a[i])
			{
				max2 = max;
				max = a[i];
			}
			else
				max2 = a[i];
		}	
	}
	printf("数组中第二大的值为:%d\n",max2);
	return 0;
}

题目:将一个数组中的负数放到正数的前面

//将一个数组中的负数放到正数的前面
#include<stdio.h>
int main()
{
	int a[5]={-1,4,7,-5,9};
	int i,j,k;
	for(i = 0;i<5;i++)
	{
		if(a[i]>0)
		{
			k = i;
			break;
		}
	}
	while(i<4)
	{
		if(a[i+1]<0)
		{
			a[k]=a[k]^a[i+1];
			a[i+1]=a[k]^a[i+1];
			a[k]=a[k]^a[i+1];
			++k;
		}
		i++;
	}
	for(j=0;j<5;j++)
	{
		printf("%d\t",a[j]);
	}
	printf("\n");
	return 0;
}

五、 多维数组

二维数组定义:
数据类型 数组名 [行的大小] [列的大小]

如:

int arr[3][5];

行和列的大小跟一维数组里面的个数的给定方式一样
一般我们给常数表达式,如果你要用变量也是可以的
但是用了变量你就不能初始化,而且你用的变量必须要有确定的值

二维数组在内存的分布

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6HEaMop3-1625710547557)(E:\粤嵌学习笔记\C语言\二维数组内存.png)]

二维数组的初始化

1 .我们可以分行对二维数组进行初始化

int a[2][3] = {
			{1,2,3},
			{4,5,6}	
		};

2.我们可以将上述的这种形式写在一个或括号里面

int a[2][3] = {1,2,3,4,5,6};		

3.部分初始化 剩余没有初始化的会自动置0

int a[2][3] = {
		{1,2},   //第一行初始化2个 第三个为0
		{4,5}	//第二行初始化2个 第三个为0
	};

int a[2][3] = {1,2,4,5};   //-> 第一行全部初始化  	1 2 4
								//第二行只会初始化1个	5 0 0

4 .如果对于一个二维数组全部初始化 那么我们可以省略行的个数,但是列是不能省略的

	int a[][3] = {
		{1,2,3},
		{4,5,6}	
	};
//或者

	int a[][3] = {
		1,2,3,4,5,6				
	};

//或者
	char name[][16] = {
		"penglei",
		"henshuai",
		.....
	};

二维数组元素的引用

1.单个元素引用 -> 数组名[行] [列] (行列的下标都是从0开始)

2.想用一行数据 -> 数组名[行] -> 数组名[行]所代表的就是一行数据

既然二维数组本质上就是一维数组 ,那么我们也可以搞一个指针直接去用一里面单个的元素

a[0] ->代表的第一行, 就是第一行的首地址

六、二维数组相关题目

题目:二维数组最大最小值

1.求一个二维数组的最大值与最小值,以及打印出数组的和

//求一个二维数组的最大值与最小值,以及打印出数组的和
#include<stdio.h>
void max_min_sum(int arr[2][3], int a, int b);
int main()
{
	int arr[2][3]={4,5,2,6,2,3};
	max_min_sum(arr, 2,3);
	return 0;
}
void max_min_sum(int arr[2][3],int a,int b)
{
	int i,j,max = arr[0][0],min = arr[0][0],sum = 0;
		for(i = 0;i<a;i++)
		{
			for(j = 0;j<b;j++)
			{
				sum += arr[i][j];
				if(max < arr[i][j])
				{
					max = arr[i][j];
				}
				if(min > arr[i][j])
				{
					min = arr[i][j];
				}
			}
		}
		printf("max = %d,min = %d,sum = %d\n",max,min,sum);
}

题目:求和最大的行和列

2.求一个二维数组里面元素之和最大的那一列和那一行

//求一个二维数组里面元素之和最大的那一列和那一行
#include<stdio.h>
int main()
{
	int arr[3][3]={2,4,5,1,6,3,2,9,3};
	int i,j,r_max,c_max,sum,row,col;
	for(i = 0;i<3;i++)		//行求最大和并记录下标
	{
		sum = 0;			//重置和
		for(j = 0;j<3;j++)	//求i行的和
		{
			sum += arr[i][j];
		}
		if(r_max<sum)		//把行最大和赋值给r_max
		{
			r_max = sum;
			row = i;
		}
	}
	for(i = 0;i<3;i++)		//列求最大和并记录下标
	{
		sum = 0;			//重置和
		for(j = 0;j<3;j++)	//求i行的和
		{
			sum += arr[j][i];
		}
		if(c_max<sum)		//把行最大和赋值给c_max
		{
			c_max = sum;
			col = i;
		}
	}
	printf("第%d行和最大,值为%d,第%d列和最大,值为%d\n,",row,r_max,col,c_max);
	return 0;
}

题目:求山顶元素

3.山顶元素:比左右上下都大的就是山顶元素

方法1:可以,但不够简单

//求山顶元素
//山顶元素:比左右上下都大的就是山顶元素
//该代码思路:把需要判断的数组放入一个比它大一圈数组(解决接下来判断涉及到的越界问题),
//使得需要判断的数组周围都是0
#include<stdio.h>
int main()
{
	int i,j;
	int a[3][3]={5,2,6,4,13,55,4,3,9};
	int b[5][5]={0};
	for(i = 1;i<4;i++)
	{
		for(j = 1;j<4;j++)
		{
			b[i][j] = a[i-1][j-1];
		}
	}
	for(i = 1;i<4;i++)
	{
		for(j = 1;j<4;j++)
		{
			if(b[i][j]>b[i-1][j]&&b[i][j]>b[i+1][j]&&b[i][j]>b[i][j-1]&&b[i][j]>b[i][j+1])
				printf("%d为山顶元素\n",b[i][j]);
		}
	}
	return 0;
}
/*该代码对存在负数的数组不成立
改进:先遍历数组a,找出数组a中的最小值,再将最小值减1作为b的初始化值*/

方法二:简单高效

//题目:求山顶元素。老师代码:使用惰性运算
//思路:if里面写4个条件,依次判断元素是否大于上下左右的值。
/*
条件1:左边有值||元素>左边元素			       ->左边有值才会判断右边
条件2:右边有值||元素>右边元素
			....
最后:条件1&&条件2&&...
*/
#include<stdio.h>
int main()
{
	int i,j;
	int a[3][4]={45,5,2,12,7,8,34,56,22,11,4,1};
	for(i = 0;i<3;i++)
	{
		for(j = 0;j<4;j++)
		{
			if((i == 0||a[i][j]>a[i-1][j])&&(i == 2||a[i][j]>a[i+1][j])
				&&(j == 0||a[i][j]>a[i][j-1])&&(j == 3||a[i][j]>a[i][j+1]))
				printf("%d是山顶元素\n",a[i][j]);
		}
	}
	return 0;
}
/*班上大多数同学使用的方法:
用了9个if,把每种情况都下该做哪几步,都写出来了*/

题目:输出杨辉三角

4.输出杨辉三角的前10行
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1

//输出杨辉三角的前10行
//方法1:使用一维数组,每更新一次数组输出一次
#include<stdio.h>
int main()
{
	int a[10]={1,1};
	int i,j,k;
	for(i = 0;i<10;i++)
	{
		a[i] = 1;
		for(k = i-1;k>0;k--)
		{
			a[k] = a[k]+a[k-1];
		}
		for(j = 0;j<=i;j++)
		{
			printf("%d\t",a[j]);
		}
		printf("\n");
	}
	return 0;
}

//杨辉三角输出
//方法2:使用二维数组,依次给每一个数组元素赋值,
//每次输出一行的前(行号+1)个元素
#include<stdio.h>
int main()
{
	int i,j;
	int a[10][10];
	printf("1\t");
	printf("\n");
	for(i=1;i<10;i++)
	{
		for(j = 0;j<=i;j++)
		{
			if(0 == j || i == j)
			{
				a[i][0] = a[i][i] = 1;
			}
			else
			{
				a[i][j] = a[i-1][j] + a[i-1][j-1];
			}
			printf("%d\t",a[i][j]);
		}
		printf("\n");
	}
	return 0;
}

题目:高数据占座问题

5.高数据占座问题
​ 有一个人叫高数据 它要给它和它的2个室友(3个人)去占座位
​ 它有一个习惯 它不能和它的室友分开,并且不能前后坐
​ 只能三个人连在一起 并且座位已经有一些被占了
​ 写代码去求一下他们有多少种占法
​ 自己去给这个座位

//高数据占座问题
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
	srand((int)time(NULL));
	int i,num = 0;
	int a[100] = {0};		//100个座位
	for(i = 0;i<rand()%50;i++)	//随机占用了随机个座位
	{
		a[rand()%100] = 1;
	}
	for(i = 0;i<100;i++)
	{
		if(a[i]==0 && a[i+1]==0 && a[i+2]==0)	//判断是否有连续的三个空位
		{
			num++;
		}
	}
	printf("%d\n",num);
	return 0;
}

题目:最大子数组和

6.求一个一维数组最大子数组(连续的)的和
2 -1 -3 4 5 -8 -9 10 11 -2
最大的子数组为
10 11 和为21
1 .暴力破解: 列觉所有的情况, 得出最大值
2 .sum只要加到了小于0的情况, 那么直接等于0

#include <stdio.h>
int main()
{
	int a[10] = {-10,3,3,-4,5,-3,0,-20,-30,10000};
	int sum = a[0];
	int sum_max = sum;
	int i = 0;
	for( ;i < 10;i++)
	{
		sum += a[i];
		if(sum < 0)
		{
			sum = 0;
		}
		if(sum_max < sum)
		{
			sum_max = sum;//更新max
		}		
	}
	if(sum_max <= 0)
	{
		sum_max = a[0];
		//遍历最大值就可以了
		for(i = 0 ;i < 10;i++)
		{
			if(sum_max < a[i])
			{
				sum_max = a[i];				
			}				
		}
	}
	printf("%d\n",sum_max);
	return 0;

}
  1. 其他方法
//求一个一维数组最大子数组(连续的)的和
//例:2 -1 -3 4 5 -8 -9 10 -2 12 	最大的子数组为10 -2 12 和为20
#include<stdio.h>
int main()
{
	int a[10]={2,-1,-3,4,5,-8,-9,10,-2,12};
	int i,j,sum = 0,max_sum = 0,flag_i,flag_j;
	for(i = 0;i<10;i++)				//外循环
	{
		sum = 0;
		for(j = i;j<10;j++)			//内循环
		{
			sum += a[j];
			if(sum>max_sum)
			{
				max_sum = sum;
				flag_i = i;			//记录和最大的数组字段开始位置
				flag_j = j;			//记录和最大的数组字段结束位置
			}
			else if(sum<0)
			{
				i = j+1;
				break;
			}
		}
	}
	printf("最大子数组为:");
	for(i = flag_i;i<=flag_j;i++)
	{
		printf("%d\t",a[i]);
	}
	printf("\n");
	printf("和为:%d\n",max_sum);
	return 0;
}
/*
原来的代码:
思路:只要遇到一个负数,就认为前面这段子数组不是最大子数组段,也就是
说我之前认为的最大子数组字段里面是不能有负数的,以下代码实现的寻找数组
中和最大的正数子数组段。
for(i = 0;i<10;i++)				//外循环
	{
		sum = 0;
		for(j = i;j<10;j++)		//内循环
		{
			flag_i = i;
			if(sum<(sum + a[j]))
			{
				sum = sum + a[j];
				flag_j = j;
			}
			else 
			{
				i = j + 1;
				break;
			}
		}
	}

*/

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值