目录
冒泡排序:数组中两个相邻的元素进行比较,如果不满足条件就交换
什么是数组?
数组是一组相同类型元素的集合。
例如:int arr [ 100 ] ;
int arr [ 10 ]={ 1,2,3,4,5,6,7,8,9,10 };
数组的创建:
创建时可以用变量吗?
例如:
int n=10;
int arr[n];
//变长数组
//这个n是根据变量n而决定的
C99中引入了变长数组的概念,允许数组的大小用变量来指定,如果编译器不支持C99中的变长数组,那就不能使用
VS2019是不支持变长数组的
并且变长数组是不能初始化的。
const int n=10;
int arr[n];
//用const修饰的叫常变量,本质上还是变量。不能这样使用
数组的初始化:
1.int arr[10]={1,2,3,4}; 这种是不完全初始化,他会把初始化1,2,3,4后,剩下六个默认初始化为0。
2.当初始化了后,数组大小可以不写,他会自动根据内容识别的大小
3.字符默认就是以ascii码值存储的
char arr4[3] = {'a',98, 'c'};
char arr5[] = {'a','b','c'};
这样写也是可以的,这两种的效果都是一模一样的,b的ascii码值就是98
4.如果不初始化,将会是随机值。
5.局部变量的int a;实际上也是随机值。但是全局变量的int a,那么他就会自动初始化为0;
静态变量也是默认初始化为0
只要变量是在静态区上开辟的,这上面的变化会默认初始化为0。栈上开辟的变量,不初始化就会是随机值。
(4)
char arr1[ ]="abc" // a b c \0 放了四个字符
char arr2[ ]={‘a','b','c'} //只放了三个字符
但是如果我们这样写
char arr1[ 5 ]="abc" // a b c \0 \0
char arr2[ 5 ]={‘a','b','c'} //默认初始化三个字符,后面放\0
5.如果要存0-n个字符,可以用循环
下标引用操作符 [ ] 是从0开始的
int main()
{
int arr[200] = {1,2,3,4,5,6};
//printf("%d\n", sizeof(arr));//400
//printf("%d\n", sizeof(arr[0]));//4
int sz = sizeof(arr) / sizeof(arr[0]);//计算数组元素个数的写法
// 0 1 2 3 4 5
int i = 0;
//赋值
for (i = 0; i < sz; i++)
{
arr[i] = i + 1;
}
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
打印了0-200个数字
6.一维数组在内存中的存储:
1. 1-10每个数都是4个字节,并且都是差4。
2.所以说一维数组在内存中是连续存放的!!!!
3.随着数组下标的增长,地址是由低到高变化的
7.通过指针,该如何访问?
由此可见,p+1实际上跳了四个字节。
所以,通过指针也是能正常访问的
下标可以访问,指针也能访问,都没有问题。
%p是打印地址(十六进制)的。
char*的指针,+1,就是跳过一个字符一个指针
二维数组
二维数组的创建:
int arr[3][4]; 三行四列
char arr[3][5]; 三行五列
double arr[2][4]; 二行四列
第一行有五个元素,一共三行
int arr[3][5]={ 0 } //完全初始化,比较常用
int arr[3][5]={1,2,3,4,5,6} //不完全初始化
很明显,一行初始化完了,才会初始化第二行,其他的初始化为0
int arr[3][5]={ {1,2} , {4,5} , {5,6 } };
这种就是将1,2放到第一行,4,5放到第二行,5,6放到第三行,每一行未涉及的部分初始化为0
注意:
1.行可以省略,但列不能省略,他会根据初始化内容自动确定要多少行。
如何访问?
**行和列,都是从0开始的**
指定行和列,就可以锁定元素了
所以:
便可以访问
当然也可以这样写:
int arr2[][5] = { {1,2}, {4,5},{5,6} };
int i = 0;
for (i = 0; i < sizeof(arr2)/sizeof(arr2[0]); i++)//0 1 2 第一行是一维数组,确定了几行
{
int j = 0;
for (j = 0; j < sizeof(arr2[0])/sizeof(arr2[0][0]); j++) //第一行的大小,除以第一行第一个元素的大小,确定了几列
{
printf("%d ", arr2[i][j]);
}
printf("\n");
}
二维数组在内存中又是如何存储呢?
二维数组也是一行一行放的,所以说列不能省,行可以。
二维数组其实也就类似于一类数组,第一个是arr[0][j],第二个是arr[1][j]等等
数组越界
下标都是从0开始的,最大的就是n-1。如果小于0,或者大于n-1,就是数组越界了。而且C语言本身是不检查数组越界的,编译器也不报错,语法也没问题,所以得靠我们自己去检查判断
冒泡排序:数组中两个相邻的元素进行比较,如果不满足条件就交换
先写个框架:
void bubble_sort(int arr[])
{
}
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
//写一个冒泡函数的函数,来排序arr[]
bubble_sort(arr);
return 0;
}
第一趟,把9排到他该出现的地方,再第二趟排8,就这样继续往下走。每一趟搞定一个。10个元素,就需要9趟这样的排序。
数组名是什么?
在绝大情况下,数组名就是首元素的地址。有两个例外,
第一个例外是sizeof()里面单独放一个数组名时,数组名就不是数组首元素地址了,而是表示整个数组。
第二种情况就是 &数组名(取地址),这种时候的数组名表示整个数组,取出的是整个数组的地址。
&arr的地址怎么和第一个一样呢?我们来+1,试一试
前两个都是+4,最后一个却加了十六进制的28,也就是40.
第二点,当数组传入函数时,传的虽说是地址,地址+1,和用下标引用符 arr[ i+1 ],效果是一样的,都能访问。
所以,最终我们可以写成:
void bubble_sort(int arr[],int kz)
{
int i = 0;
for (i = 0; i < kz-1; i++)//9趟
{
int p = 0;
for (p = 0; p<kz-1-i; p++) //当一个排完后,就可以少排一个,所以-i
{
if (arr[p] > arr[p+1])//9>8
{
int tmp = 0;
tmp = arr[p];
arr[p] = arr[p+1];
arr[p+1] = tmp;
}
}
}
}
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
//写一个冒泡函数的函数,来排序arr[]
int kz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr,kz);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
思考与改进:
当我已经发现是顺序了,我还要一个一个去对比吗?这样效率就会很慢。
我可以在走第一趟的时候,发现有没有可以交换的地方,第一趟发现他已经是顺序了,我就可以直接跳出来了。
void bubble_sort(int arr[],int kz)
{
int i = 0;
for (i = 0; i < kz-1; i++)//9趟
{
int flag = 1;
int p = 0;
for (p = 0; p<kz-1-i; p++)
{
if (arr[p] > arr[p+1])//9>8
{
flag = 0;
int tmp = 0;
tmp = arr[p];
arr[p] = arr[p+1];
arr[p+1] = tmp;
}
}
if (1 == flag)
{
break;
}
}
}
int main()
{
int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
//写一个冒泡函数的函数,来排序arr[]
int kz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr,kz);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
思考:
三子棋&&扫雷