系列文章目录
前言
今天主要讲初阶数组的最后一个知识点和一种算法思想:冒泡排序。
数组作为函数参数
例子
写一个函数对数组进行升序
int main()
{
int arr[] = {10,9,8,7,6,5,4,3,2,1};
sort(arr);
print(arr);
return 0;
}
冒泡排序的思想
两个相邻元素进行比较,然后符合要求就进行交换
思路
我们首先对数字10进行排序
10要和除本身之外的所有数进行比较,然后交换。一共比较9次。
接着从9开始
9除本身和10之外,进行8次比较
以此类推
8进行了7次比较,7进行了6次比较,……,1进行了0次比较。
总结
我们可以做个总结:我们把一个数字的全部比较叫做一趟比较,那我们这个例子有10个数字,我们就有了10-1次比较(因为最后一个数字不进行比较)。一趟比较都会让这个数字来到最终应该出现的位置,本例中的10就是进行10-1-0次比较,9进行10-1-1次比较,8进行10-1-2次比较。如果还不到没关系,我们直接看代码。
代码实现
我们利用两个for循环来实现。第一个for循环代表多少趟冒泡排序,第二个for循环代表这趟冒泡排序中这个数字比较的次数。
里面非常巧妙地用到sz-1-i,因为i的变化,每趟冒泡排序中数字比较的次数都不同但都符合要求。
问题
事实上,当我们实现这个代码时,编译器只打印了一个10。
这是为什么?这涉及到今天我们要讲到的数组作为函数参数的本质。
分析问题
先调试看看问题出在哪。监视所有与排序有关的变量。
我们可以发现两个问题。一是为什么sz的值是1,而不是10?二是为什么数组传过来的只有一个数字?
本质
我们以前就说过数组名就是数组首元素的地址,既然是地址,既然函数接收数组时写成数组的形式(int arr[]),它本质上还是一个地址(指针)(in *arr)。
这就是在函数中sizeof(arr)中,arr是地址,指针的大小就是4个或8个字节,再除以sizeof(arr[0])(首元素的大小),最终等于1的原因。
而只有一个数字,是因为它本质上是首元素的地址,显示的是这个数字。
新的疑惑以及拓展
那既然这样的话,那为什么在一些情况下,sizeof(arr)的大小就是数组的大小?
这涉及到数组名的两个特例。
一个是sizeof(数组名)内单独放数组名时,这里的数组名表示整个数组,计算的是整个数组的大小。
这可以千万不能弄混。我的理解就在主函数中我们定义的数组,我们使用它时是数组名,计算的是整个数组的大小。在把数组传给函数时,函数是用指针来接受,我们计算的是指针的大小。
二是&arr,这里的数组名表示整个数组,&arr取出的是整个数组的地址。在其余情况下,数组名都表示首元素的地址。
那arr和&arr的区别是什么?
arr表示首元素的地址,&arr表示整个数组的地址,整个数组的地址自然就是从首元素开始,所以他们两的地址相同。
验证两者的不同。
我们可以发现两个加1后的结果不同。arr+1逃过一个整形,&arr+1跳过一个整形数组。
解决问题
既然我们在函数中算数组元素个数时,接受到的数组只是一个指针,我们该怎么解决?很简单,在主函数中计算数组大小然后传过去。
小知识
为什么arr是首元素地址?
当arr是传址调用时,且数组元素个数,要创建数组和拷贝数组元素,浪费时间和空间,所以就设置arr为首元素地址。
C语言初阶的数组就已经讲完了。如果发现错误的地方,请麻烦指正,我会积极改进!感谢!