冒泡排序:将一个无序数组排序成有序数组(升序/降序)
时间复杂度O(n²)
空间复杂度O(1)
int nums[] = { 3,5,7,1,2,8,9,4,6,10 };
首先随机初始化一个无序数组 这里统一将它调整为升序(降序同理)
int main()
{
int nums[] = { 3,5,7,1,2,8,9,4,6,10 };
int numsSize = sizeof(nums) / sizeof(nums[0]);
int i = 0;
for (i = 0; i < numsSize; i++)
{
printf("%d ", nums[i]);
}
printf("\n");
bubble_sort(nums,numsSize);
for (i = 0; i < numsSize; i++)
{
printf("%d ", nums[i]);
}
return 0;
}
在冒泡排序前后分别打印一次数组 ,对比冒泡排序前后数组的变化。
接下来定义冒泡排序函数主体
void bubble_sort(int* nums,int numsSize)
{
int i = 0;
for (i = 0; i < numsSize - 1; i++)//确定冒泡排序趟数
{
//定义每一趟冒泡排序具体内容
int j = 0;
int flag = 1;//假设这趟冒泡排序已经有序
for (j = 0; j < numsSize - 1 - i; j++)//两两比较次数为numsSize-1-i次
{
if (nums[j] > nums[j + 1])
{
int tmp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = tmp;
flag = 0;
}
}
if (flag == 1)//如果flag == 1 说明此时数组已经有序
break;
}
}
其实冒泡排序的核心内容就是交换两个变量的值
参考基于交换变量的值的研究_lovepotato_的博客-CSDN博客
这里来讲一讲如何减少两两比较的次数
目录
1.首先要确定冒泡排序的趟数
趟数最多是 (数组元素个数 - 1) 次。为什么是最多呢
这里假设一个数组是完全倒序的 把它排成升序(例如如下这个数组)
int nums[] = { 9,8,7,6,5,4,3,2,1 };
从i = 0 开始 第一趟冒泡排序的实际上就是把 9 一直移动到最后 其余元素相对顺序不变
int nums[] = { 8,7,6,5,4,3,2,1,9 };
同理 第二趟冒泡排序把 8 移动到倒数第二个位置 依次类推
排到最后会发现 最后两个元素(1和2)的顺序是一趟冒泡排序中排好的,所以次数是numsSize - 1次
这就是次数最多的情况。
2.定义一趟冒泡排序的具体内容
//定义每一趟冒泡排序具体内容
int j = 0;
int flag = 1;//假设这趟冒泡排序已经有序
for (j = 0; j < numsSize - 1 - i; j++)//两两比较次数为numsSize-1-i次
{
if (nums[j] > nums[j + 1])
{
int tmp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = tmp;
flag = 0;
}
}
if (flag == 1)//如果flag == 1 说明此时数组已经有序
break;
这里有个小坑 内存for循环的循环次数是numsSize-1-i次
for (j = 0; j < numsSize - 1 - i; j++)
理由:i=0 当第一趟冒泡排序排好之后 i++变成1 ,此时最后一个元素已经定好了最终位置,只需要剩下的前8个元素进行冒泡排序即可,下标最大为numsSize -1 -i
3.减少比较次数
这里为什么要再定义一个flag变量呢?
为了减少两两比较的次数,优化算法。
在每一趟冒泡排序开始之前 初始化flag = 1 用来假设此趟冒泡排序之前数组已经有序
为什么要这样做呢?随机的数组不一定都是无序的 有可能只是其中某几个元素需要交换
例如下面这个数组
int nums[] = { 1,2,3,4,6,5,7,8,9 };
这个数组其实只需要5和6交换位置就有序了
但如果没有flag变量的话 计算机就需要从头比较到尾 每两个元素都比较一下,看看是否要交换
重复性高。
flag具体实现:
if (nums[j] > nums[j + 1])
{
int tmp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = tmp;
flag = 0;
}
在if语句中定义flag的值为0,一趟冒泡排序中,