二维数组在内存中的存储
二维数组在内存中也是连续存储的。
与上述代码一样,不同的是将——
printf("%d",arr[i][j]);改为
printf("&arr[%d][%d]=%p\n",i,j,&arr[i][j]);
打印地址用“%p”
存储方式为:一行紧跟一行后面(连续存放的)
这里我们发现可以将第一行当成一维数组,第二行当成一维数组,第三、第四......(以此类推,都是如此)
那这样可以将第一行数组名写成arr[0];第二行——arr[1];第三行——arr[2]......
通过发现,在访问第一行元素时,可以写成arr[0][ j ](j可以是0,1,2,3......),在访问下一行时,这样写arr[1][ j ],再下一行arr[2][ j ]......
在想象为一维数组时,可以将 j 表示为数组中的每个元素;arr[0]相当于一维数组的数组名。
一维数组的访问是通过数组名+下标(方括号[i])的方式来访问的。
如:arr[i] i为元素下标。
如此,在二维数组的时候也一样;arr[0]为数组名,[ j ]为下标。——arr[0][ j ]
二维数组也可以理解为是由一维数组组成的数组。
数组的作用:
1、存放数据
2、传递参数
数组作为函数参数(即函数参数部分要传递的是数组)
往往我们在写代码的时候,会将数组作为参数传给函数
比如:我要实现一个冒泡排序(这里要讲算法思想)函数将一个整形数组排序。
冒泡排序函数:bubble_sort();
冒泡排序的核心思想:两两相邻的元素进行比较,不满足条件下进行交换,以此达到我们的要求。
先一趟冒泡排序:将一个元素在不满足条件下进行交换,以此来到达该元素的最终位置。
比如:
10 9 8 7 6 5 4 3 2 1
9 10 8 7 6 5 4 3 2 1
9 8 10 7 6 5 4 3 2 1
......
9 8 7 6 5 4 3 2 1 10
将10放到原来位置后,接下来就是在开头的“9”了。
这样以此类推,最终会回到 1 2 3 4 5 6 7 8 9 10
发现:10个元素要进行9趟冒泡排序
10个元素进行9对比较;9个元素——8对;8个元素——7对......
n个元素就要进行n-1趟冒泡排序
#include<stdio.h>
void bubble_sort(int arr[],int sz){
int i=0;
for(i=0;i<sz-1;i++){
int flag=1;
int j=0;
for(j=0;j<sz-1-i;j++){
if(arr[i]>arr[j+1]){
int tmp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=tmp;
flag=0;
}
}
if(flag==1){
break;
}
}
}
int main(){
int arr[]={9,8,7,6,5,4,3,2,1,10};//对arr进行排序,排成升序
int i=0;
int sz=sizeof(arr)/sizeof(arr[0]);
bubble_sort(arr,sz);//冒泡排序函数
for(i=0;i<sz;i++){
printf("%d",arr[i]);
}
return 0;
}
这里sz-1是确定冒泡排序的趟数。
int flag=1;是假设这一趟排序的数据已经有序。
flag=0;本趟排序的数据其实不完全有序。
【注:一趟要进行几对比较才算一趟。(如:10个元素进行9对比较算一趟)】
但这种代码的写法其实效率会比较低。
如果原本就是升序的状态下,它还是会老老实实去进行(确定趟数,再确定对数,再做比较)
那可以只要将这组数进行一趟冒泡排序后,发现已经是正确的排序,那后面的就不用再进行,直接打印。(至少要进行一趟)
如:
int arr[]={0,1,2,3,4,5,6,7,8,9,10};
以上代码是已经修改好的,就是添加了flag来进行判断。
break语句用于终止循环或者说跳出switch循环的;if语句没有循环,因此break不能用在if语句中。
如:
if(1)
break;
错误的
但如果if语句在for循环内部,这时if语句里的break是作用于for循环的。(意思是满足条件下跳出循环)。
数组名是什么?
int main(){
int arr[]={1,2,3,4,5};
printf("%p\n",arr);
printf("%p\n",&arr[0]);
return 0;
}
打印结果一样。【注:*arr指对首元素地址进行解引用,最后为1】
说明数组名是首元素地址。(通常情况下)
两个例外:
1、sizeof内部单独放一个数组名表示整个数组;因此,sizeof(数组名)计算的是整个数组的大小,单位是字节。
2、&数组名(取地址数组名),数组名代表整个数组,&数组名,取出的是整个数组的地址。
除此1,2两种情况之外,所有数组名都表示数组首元素的地址。
要点:
int arr[]={1,2,3,4,5,6,7};
printf("%p\n",arr); +1:00——04
printf("%p\n",&arr[0]);
printf("%p\n",&arr);
这三个打印结果一样,但寓意不一样。
前两个表示首元素地址,第三个是指整个元素从首元素开始(包括整个元素地址),因此,打印结果一样。
但如果每个加1来看的话,首元素加1的话,就指第二个元素(前两个);第三个的话从“00”变到“1c”c1指16,c指12(十六进制)12+16=28;地址增加了28
每个元素7个字节(4×7=28),加1后整个数都包括了。
补充:下标为0的元素为首元素。
这里补充一个知识点——
- char c[3][8]={{"apple"},{"orange"},{"banana"}};等价于
- char c[3][8]={"apple","orange","banana"};