据说在计算机发明后的很长一段时间内,30%以上的算力都是用来做排序这一件事情。
很久以来,自己由于习惯于依赖各种现成的库,对于各种排序算法生疏久已,甚至对于选择、冒泡、插入等排序的区别都有些模糊不清了。我们庆幸于生在这个年代,安心享受着前辈大师们的智慧结晶,可以说是站在巨人的肩膀上眺望远方了。此篇博客用来总结各种排序算法,强化对算法重要性的认识,并且向各位对排序算法做出改进的大师们致敬了。
一、选择排序
·算法描述
首先,找到数组中最小的那个元素,使它和数组中的第一个元素交换位置;再次,在剩下的元素中继续找最小的那个,使他和数组中的第二个元素交换位置。如此往复,直到整个数组排序。
·算法特点
1、运行时间和输入无关
一个有序的数组和一个元素随机排列的数组,排序的时间复杂度竟然一样。
2、数据移动是最少的
数据交换只在最内层循环之外的地方发生。交换的次数和数组的大小是成线性关系的,我们研究的其他算法都不具备这个特征
·时间复杂度分析
对于长度为N的数组,选择排序需要N2/2次比较和N次交换。总的来说时间复杂度为平方级别O(N2)
·空间复杂度分析
基本不占用多余的内存空间,复杂度为O(1)。
·适用情景
任何刚学编程的菜鸟的第一思路基本就是这个了:)
·示例代码
//选择排序
void selectSort(int *a,int size)
{
for(int i = 0; i < size; ++i)
{
//最小值索引
int minIndex = i;
for(int j = i+1; j < size; ++j)
{
//查找最小值的索引
if(*(a+j) < *(a+minIndex))
{
minIndex = j;
}
}
//交换数组中两个位置的值
if(minIndex != i)
{
int tmp = *(a+i);
*(a+i) = *(a+minIndex);
*(a+minIndex) = tmp;
}
}
}
二、冒泡排序
三、插入排序
·算法描述
我们平时打扑克摸牌时,每摸到一张牌,就要插入到手中已排好序的所有牌中,插入排序的算法跟这个很相似。数组左侧都是已拍好序的元素,读取右侧的每一个元素,都要插入到左侧的有序元素中去,左侧的有序元素,会根据新插入元素的位置,做部分整体的向右移位,当所有元素都已插入完毕时,排序结束。
·算法特点
·时间复杂度
·空间复杂度
·适用情景
·示例代码
//插入排序
void insertsort(int *a,int size)
{
for(int i = 1; i < size; ++i)
{
for(int j = i; j > 0; j--)
{
if(*(a+j) < *(a+j-1))
{
int tmp = *(a+j);
*(a+j) = *(a+j-1);
*(a+j-1) = tmp;
}
else
{
break;
}
}
}
}