*c语言学习笔记(十五)*
冒泡排序算法
算法练习,设计一个冒泡函数,对整型数组进行排序
1、什么是冒泡排序算法
将两两相邻元素进行比较,然后得到一个新数列,诸如此循环直到所有的元素全部完成两两比较,这就完成了一次冒泡排序;所以假设数组内有是个元素,那么我们需要九次冒泡排序才能全部完成比较。
2、数组传参问题:这个问题也已经写过很多遍了,由于比较重要,这里就再写一遍,当数组传参时,传递过去的并不是整个数组,而是数组首元素的地址
老师给出的代码如下:
void bubble_sort(int arr[],int sz)
{
int i = 0;
for (i = 0; i < sz - 1; i++)
{
int j = 0;
for (j = 0; j < sz - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main()
{
int i = 0;
int arr[] = { 9,8,7,6,5,4,3,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
printf("想要比较的初始数组顺序为:\n ");
for (i = 0; i < 9; i++)
{
printf("%d ", arr[i]);
}
bubble_sort(arr,sz);
printf("\n冒泡排序完成后数组顺序:\n");
for (i = 0; i < 9; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
运行结果为:
如果我们加上scanf函数,即可完成任意给定的数组进行冒泡排序;
对于上面的代码,使用两层for’循环来完成所有的冒泡排序,外层的for循环,完成的是每一次冒泡排序,即外层循环+1时,我们的冒泡排序就完成了一次,数组内的一次两两比较结束了。内层循环是两两比较循环,并且把较大的数存储在后面一位。
但是上面这种程序存在着很大局限性,无论我们给出什么样子的数组,他都会从头开始比较,过程非常复杂,造成了代码重复率高,效率低;
在源代码的基础上,我们做出以下修改,添加一个标志位用来检验是否数组内所有的数据全部已经顺序对了,如果对了,那么将标志位置1并且跳出循环,如果发生了移位,那么就说明换位还没有结束,将标志位置0并继续冒泡排序
代码如下:
void bubble_sort(int arr[],int sz)
{
int i = 0;
for (i = 0; i < sz - 1; i++)
{
int j = 0;
int flag = 1;
for (j = 0; j < sz - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
flag = 0;
}
}
if (flag == 1)
{
break;
}
}
}
主函数不变,在bubble函数中进行修改;通过标志位,我们可以提前察觉数组排序完成了,减少了后面很多不必要的重复;
注:break语句仅能在循环或者switch语句中使用,因为我们的if语句是在for循环里面的,所以可以在这里写break语句;
为了验证数组传参是首元素的地址的问题,我们可以做出一下实验:
int arr[] = { 9,8,7,6,5,4,3,2,1 };
printf("%p \n", arr);
printf("%p \n", &arr[0]);
printf("%d ", *arr);
当写出上面代码,若我们的假设正确,那么第一行,第二行应该是同一个地址,而第三行则是首元素的值“9”
运行结果如下:
正确。