一、简介
最近学习了几种常见的排序方法——冒泡、插入、选择排序、堆排序、归并排序以及快速排序。加入了一写自己的想法和理解
二、冒泡排序
具体代码如下:
void buttle_sort(int date[], int num) //date是一个数组,num是数组的大小
{
for (int i=0; i<num-1; ++i)
{
for (int j=0; j<num-1-i; ++j) //第一次循环j最大为num-1,执行i次循环,j的最大值就会减少i
{
if (date[j] > date[j+1]
swap(date[j], date[j+1]);
}
}
}
分析:
1、第一层的 for 循环可以理解为 num 个数组,需要经过 num-1 个循环才可以变成有序数组;
2、第二层的 for 循环可以理解为在大循环下面有多少个数需要进行比较;
当i=0的时候,j 需要依次和 j+1 进行比较,所以 j 最大可以为 num-1(当 j = num 的时候, j+1 = num+1,超出了数组的长度);运算完后,数组的最后一个元素为该数组最大的元素,此时最后一个元素不再参与下次运算,所以下次参与运算的个数与大循环中 i 的值有关(i 每执行完一次循环,就少一个数参与下次循环)
3、当 date[j] <= date[j+1] 的时候,程序继续执行;当 date[j] > date[j+1] 的时候,交换两个数组的位置。此处调用了 swap 函数;
4、时间复杂度分析:第一次大循环里面需要循环n-1次,第二次虚幻需要循环n-2次…根据累加公式可以计算出时间复杂度是O(n^2)
5、问题:是不是一定要执行 num-1 次循环?
问题解答:
分析:假如原数组是 {1, 2, 3, 4, 5, 6} 时,第一次循环没有元素交换(已经是有序的了),此时程序依然会执行下一次循环;此时就做了多余的工作。
改进:当某次循环,发现这个数组已经是有序(没有元素进行交换)的时候,程序就直接跳出。
void buttle_sort(int date[], int num)
{
for (int i=0; i<num-1; ++i)
{
int flag = 0; //判断是否有元素进行交换
for (int j=0; j<num-1-i; ++j)
{
if (date[j] > date[j+1]
{
flag = 1;
swap(date[j], date[j+1]);
}
}
if (flag == 0)
break;
}
}
分析:
1、flag 此处是一个标志,没有元素进行交换的时候 flag = 0,当进行数字交换的时候 flag = 1;当某次循环结束的时候 flag == 1 时,说明此时数组还不一定是有序的;但当某次循环结束的时候 flag == 0 则说明此时数组已经有序;
2、时间复杂度分析:最好的情况是已经有序,此时只循环一次;最坏的情况是倒序,循环次数同上;所以平均时间复杂也是O(n^2);