这里主要解释冒泡排序和插入排序的常见问题的解析:
1.在元素基本有序的情况下,哪一个比较好?
2.同为稳定性排序算法,时间复杂度也一样,插入排序的效率比冒泡排序要好,尤其是数据量大的时候,差距更明显。为什么?
- Q1:通过冒泡排序(改进后)和插入排序的学习,发现两者有相似的地方,并且在元素基本有序的情况下的,两者之间的性能比较有困惑。
因为同样在最好的情况下(序列有序)的时间复杂度是O(N),并且交换元素的次数都是逆序对的个数I
,那么如何进一步的分析性能呢?到底谁更好呢?
(暗示一下:两种算法元素交换的次数都是逆序对的次数)
冒泡排序法和插入排序法的核心思想就是元素交换,虽然整体的结构都是两层的循环嵌套,但是两者的交换过程又不尽相同。
(代码的实现可能和你的不一样但是思想都是相同的)
从小到大排序
- 冒泡排序的代码
void Bubble_Sort(int A[],int N)
{
int flag;
for(int p = N-1;p>=1;p--)//总共需要n-1次排序
{
flag = 0;
for(int i = 0;i<p;i++)
{
if(A[i]>A[i+1])//两两元素比较,严格大于才开始交换
{
flag = 1;
swap(A[i],A[i+1]);
}
}
if(flag == 0)
return ;
}
}
每一次的排序过程都是将待排序列中最大的元素放到最下方(通过所有待排元素的两两比较实现的,也就是说一次的排序过程需要比较所有的元素,虽然这个过程不一定发生交换)
- 插入排序的代码
void Insertion_Sort(int A[],int N)
{
for(int p=1;p<=N-1;p++)//第一张牌可以看成有序,后面n-1个元素都需要插入
{
int tmp = A[p];
for(int i = p;i>0 && A[i-1]>tmp;i--)//i可以当做待插入的位置
{
A[i] = A[i-1];
}
A[i] = tmp;
}
}
每一步将一个元素插入到合适的位置(通过将当前的待排元素和之前排好序的有序序列相比较,但是这个比较的过程并不是需要每一个元素都比较,一旦发现当前待插入元素比有序序列某一个数大就不需要和前面的数比了)
- **小结:*(同样在最好的情况下(序列有序)的时间复杂度是O(N),并且交换元素的次数都是逆序对的个数
I
)
第一点、插入排序 比较次数应该更少,因为冒泡移动过程中都是与无序的数组进行交换, 插入排序可以提前退出内部循环,一旦发现自己比有序序列某一个数大就不需要和前面的数比了
第二点 、同样是元素的交换,但是冒泡排序的交换是使用swap(),每一次元素的交换都是3步。而插入排序的算法的交换其实是 移动 ,将前面的元素向后面移动一个位置即可。大大提高了效率。
所以,我认为在元素基本有序的情况下,插入排序比改进后的冒泡排序的性能更好(元素交换的次数都是相同的,主要是比较的此时不同)。
Q2:插入排序和冒泡排序的时间复杂度都是O(n2),可实际开发中,为什么我们更倾向于使用插入排序算法呢?
具体的问题可以参见排序算法问题描述
这里,相对于原博文我加入自己的分析:
1.插入排序元素间比较的次数更少
2.冒泡排序的移动操作更多(因为冒泡排序的两个元素间的一次交换就需要3次移动)
最后大家可以把自己的想法写下,大家交流,一起进步。