一、数组的特点:
- 一致性:同类型数据集合,定义的数组中所有的元素都是同样类型的;
- 有序性:因为是线性的,所有元素都有严格的前后关系,不是指排过序的;
- 连续性:指的是顺序存储关系,数组要求该数组中所有的数据元素存储空间是一块连续的存储空间。
# include <stdio.h>
# include <stdlib.h>
#include <time.h>
int main()
{
srand(time(NULL));//在产生随机数之前将当前系统时间放进去,将当前系统时间作为初始值,注意包含头文件#include <time.h>
int len=10;//const int len=10,也不能直接将len写入数组的方括号中,除非定义一个宏#define LEN 10.
int a[10];//里面只能是常量或常量表达式,不能是小数,里面代表的是数组元素的个数,也可以是'a',必须指明数组大小,不能为负,最小是1。
a[0]=1;
for(int i=1;i<10;++i)
{
a[i]=rand()%6+1;//掷色子,需包含头文件#include <stdlib>
}/*rand()标准C库提供的随机的整型数据,值是从0~32767的伪随机数(因为产生随机数后几次输出的数是一样的),计算机很难产生一个真正的随机数,因为计算机里没有产生随机数的硬件,计算机里的随机数是要通过特定的算法算出来的,这个算法他需要一个初始值*/
return 0;
}
//下标(索引)index;基于0的。
下标可以是变量或是变量表达式,编译器对数组下标越界无能为力,因为下标为变量的时候,变量在编译期间值是可以变得,所以编译器对数组下标越界本身也是无能为力的。
二、一维数组初始化
初始化:在变量定义的同时赋予初值;
int a[10]={1,2,3,4,5,6,7,8,9,10}//挨个儿元素赋初值并用逗号隔开;
int a[10]={1,2,3,4,5};//如果只给数组部分元素初始化,则未被初始化的元素全为0(若为整型则为0,浮点型为0.0,字符型则为ASCⅡ码值为0的字符'\0'),即未初始化元素以位模式清零。
int a[]={1,2,3,4,5};//如果给数组所有元素初始化,则数组长度可以不写,编译器会自动根据初值个数来确定数组长度,如果数组长度大于初值个数则编译器报错,即可小于等于但不能大于。
int len=sizeof(X);//求后面括号里面的X(可以是变量名或是类型名也可以是表达式,但是该表达式一定要有类型)所占存储空间的大小,单位是字节byte,X如果是表达式,则该表达式不参与运算。
int len=sizeof(a)/sizeof(a[0]);//求当前数组元素的个数,写a[0]的原因是万一数组中只有一个数。
三、斐波那契
int main()
{
int a[20] = { 1, 1 };
int len = sizeof(a) / sizeof(a[0]);
for (int i = 2; i < len; ++i)
{
a[i] = a[i - 1] + a[i - 2];
}
for (int i = 0; i < len; ++i)
{
printf("%d,", a[i]);
}
puts("");
return 0;
}
四、排序
冒泡排序
int main()
{
int a[] = { 7, 4, 8, 3, 9, 2, 1, 0, 6, 5 };
int len = sizeof(a) / sizeof(a[0]);
int t;
for (int i=0; i < len-1; ++i)
{
for (int j = 0; j < len - 1 - i; ++j)
{
if (a[j]>a[j+1])
{
t = a[j];
a[j] = a[j+1];
a{j +1 } = t;
}
}
}
for (int i = 0; i < len; ++i)
{
printf("%d,"a[i]);
}
return 0;
}
时间复杂度:用待处理数据的个数表示的算法中基本操作的次数的方程的最高次项。
排序稳定性:
稳定排序:相等元素在排序前后的相对位置没有变化。
四、堆排
int main()
{
int a[] = { 1, 9, 8, 7, 3, 8, 5, 9, 6, 8, 3 };
int b[10] = { 0 };
int len = sizeof(a) / sizeof(a[0]);
for (int i = 0; i < len; ++i)
{
b[a[i]] += 1;
}
for (int i = 0; i < 10; ++i)
{
for (int j = 0; j < b[i]; ++j)
{
printf("%d,",i);
}
}
return 0;
}
五、求最大值
int main()
{
int a[] = { 2,- 8, -3, 7, 9, 3, -6, 4, 1 };
int max = 0;
int len = sizeof(a) / sizeof(a[0]);
for (int i = 1; i < len; ++i)
{
if (a[i]>a[max])
{
max = i;
}
}
printf("max=a[%d]=%d\n", max,a[max]);
return 0;
}
#include <stdio.h>
六、二维数组
int main()
{
int a[3][4];
int len1 = sizeof(a) / sizeof(a[0]);
int len2 = sizeof(a[0]) / sizeof(a[0][0]);
printf("%d\n", sizeof(a[0]));
printf("%d\n", sizeof(a));//会输出48
//双循环遍历,行优先遍历的效率高于列优先遍历
for (int i = 0; i < len1;++i)
{
for (int j = 0; j < len2; ++j)
{
a[i][j] = i*4+j+1;
}
}
//a[i][j]在内存中存的不是行列结构,而是线性结构,内存中i*len2+j这样遍历的
//a[1][5]=99并没有越界,表示线性元素下标是a[2][1]的元素。
//计算二维数组是否越界,二维转一维([i][j]->[m],i*len2+j),一维转二维([x]->[i][j],[x/len2][x%len2).
for (int i = 0; i < 3;++i)
{
for (int j = 0; j < 4; ++j)
{
printf("%-3d", a[i][j]);
}
printf("\n");
}
return 0;
}
a[3][4] = { a[0], a[1], a[2] };
a[0] = { a[0][0], a[0][1], a[0][2], a[0][4]; }a[0]是一个有四个元素的一维数组的数组名。
七、二维数组初始化
int main()
{
int a[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12};
int a[3][4] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
int a[3][4] = {
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 } };//与第二个相比一般写这个,与第一个的区别是若删去某个元素,则最后的结果可能不同。
int a[][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };//不能行和列都不写,按照双下标访问的时候不能进行定位,第一个能省,第二个不行,对任何多维数组而言只能省第一个。
//数组初值个数只能少不能多,少的补,位模式清零
int len1 = sizeof(a) / sizeof(a[0]);
int len2 = sizeof(a[0]) / sizeof(a[0][0]);
for (int i = 0; i < 3;++i)
{
for (int j = 0; j < 4; ++j)
{
printf("%-3d", a[i][j]);
}
printf("\n");
}
return 0;
}
八、数组的行列元素互换(数组的转置)
int main()
{
int a[3][3] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };//方的,可以原地转置
int t;
//注意不要换主对角线,也不能多换,换过去又换回来
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < i; ++j)
{
t = a[i][j];
a[i][j] = a[j][i];
a[j][i] = t;
}
}
return 0;
}
九、水平镜像(每一行做一个逆序)
int main()//一维数组镜像
{
int a[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8 };
int len = sizeof(a) / sizeof(a[0]);
int t;
for (int i = 0; i < len; ++i)
{
t = a[i];
a[i]= a[len - 1 - i];
a[len - 1 - i] = t;
}
for (int j = 0; j < len; ++j)
{
printf("%-3d", a[j]);
}
return 0;
}
int main()//二维数组水平镜像
{
int a[3][3] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };//方的,可以原地转置
int t;
//注意不要换主对角线,也不能多换,换过去又换回来
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 3/2; ++j)
{
t = a[i][j];
a[i][j] = a[i][3-1-j];
a[i][3-1-j] = t;
}
}
return 0;
}
//a[N][N]:转置,水平镜像,垂直镜像(每一列逆序),顺时针转90度,逆时针90度(水平镜像和转置),一百八十度。测试用例:俄罗斯方块
十、找极值
int main()
{
int a[3][4];
int len1 = sizeof(a) / sizeof(a[0]);
int len2 = sizeof(a[0]) / sizeof(a[0][0]);
for (int i = 0; i < 3;++i)
{
for (int j = 0; j < 4; ++j)
{
scanf("%d", &a[i][j]);
}
}
int row, col;
row = col = 0;
for (int i = 0; i < 3;++i)
{
for (int j = 0; j < 4; ++j)
{
if (a[i][j]>a[row][col])
{
row = i;
col = j;
}
}
}
printf("-----------------------------\n");
printf("max:a[%d][%d]=a[%d][%d]\n", row, col, a[row][col]);
for (int i = 0; i < 3;++i)
{
for (int j = 0; j < 4; ++j)
{
if (a[i][j] = a[row][col])
{
printf("max:a[%d][%d]=a[%d][%d]\n", i, j, a[i][j]);//如果有两个数一样大,必须重新遍历一遍查找其值。
}
}
}
/*for (int i = 0; i < 3;++i)
{
for (int j = 0; j < 4; ++j)
{
printf("%-3d", a[i][j]);
}
printf("\n");
}*/
return 0;
}
十一、最长前缀匹配
int main()
{
int a[] = { 2, -3, 4, -5, 8, -4, -7, -6 };
int len1 = sizeof(a) / sizeof(a[0]);
int sum, maxsum,end;
sum = maxsum=a[0];
end = 0;
for (int i = 1; i < len1; ++i)
{
if (sum+a[i]>maxsum)
{
maxsum=sum+a[i];
end = i;
}
sum += a[i];
}
/*
代码优化:
for(int i=0;i<len1;++i)
{
sum+=a[i];
if(sum>maxsum)
{
maxsum=sum;
end=i
}
*/
printf("a[0]--a[%d]之和最大,其值为%d\n", end,maxsum);
return 0;
}
十二、字符数组
int main()
{
char name[]=
return 0;
}
1、C语言合法字符串要有‘\0’作为结束标志;
2、字符数组可以直接用一个字符常量来进行初始化int a[] = "i miss you,and you?";
3、在字符数组中一旦遇到\0就终止了,例如:"i miss you \0 and you?"就只会出现"i miss you"后面的不会出现,但是字符串长度是不会变的。因为系统默认\0作为结束标志。
4、数组名只有在sizeof求数组长度的时候代表整个数组,在其他地方都只代表数组首元素的地址。
5、scanf在输入字符数组的时候不能输入带有空格的,printf输出的时候遇空格就终止了。因而输入字符数组用gets和puts,遇换行终止。