排序在算法中是比较基础也是相当重要的一部分,在这里将会把各种排序算法那加以总结,并实现;
堆排序 (稳定,时间 O(nlogn) )
注解:一般说快速排序是不稳定的, 但事实上快速排序有稳定的实现方法,故在这里认为快排也是稳定的
接下来会按照以下思路去分析每种排序算法:
大家也可以到这个网站上找对应排序的可视化理解各种排序算法的逻辑;
相邻两个元素进行比较然后交换;
在实现中,是以函数模板的形势实现的;利用vector
存储数组;为了方便打印每个循环中nums中的状态,调用了algorithm
库里面的for_each
函数;为了直接使用本文中的代码,需要包含的头文件有
#include
#include
#include
其他的排序算法也是如此,后面就不在重述;
template <typename T>
void bubbleSort(vector &nums){
for(size_t i = 0; i < nums.size(); i++) {
//打印出每次循环后当前的nums里面的元素
for_each(nums.begin(),nums.end(),[](const int num){ cout << num << " ";} );
cout << endl;
for(size_t j = 1; j + i < nums.size(); j++)
if(nums[j-1] > nums[j]) // keep stable
swap(nums[j-1],nums[j]);
}
}
第5行代码主要是为了方便打印每次循环后,数组里面的元素变化的状态,真正实现的时候,可以删掉这一行代码;第8行中,要注意符号,这个将会与排序算法是否稳定有一定关系
为了测试冒泡排序,主函数代码如下:
int main()
{
vector<int> nums = {8, 10, 5, 7, 11, 9, 6, 2};
bubbleSort(nums);
for_each(nums.begin(),nums.end(),[](const int num){ cout << num << " ";} );
return 0;
}
当测试其他排序算法的时候,只需要修改第3行调用排序算法的修改或者修改nums数组里面额数据即可;
测试结果:
8 10 5 7 11 9 6 2
8 5 7 10 9 6 2 11
5 7 8 9 6 2 10 11
5 7 8 6 2 9 10 11
5 7 6 2 8 9 10 11
5 6 2 7 8 9 10 11
5 2 6 7 8 9 10 11
2 5 6 7 8 9 10 11
2 5 6 7 8 9 10 11
每次选择最大(小)的元素放在数组的最后面(最前面)
template <typename T>
void selectionSort(vector &nums) {
int index;
for(size_t i = 0; i < nums.size(); i++){
index = i;
for(size_t j = i; j < nums.size(); j++) {
if(nums[j] < nums[index]) index = j;
}
swap(nums[i],nums[index]);
}
}
像打扑克牌一样,将每一张牌按照大小插入到相应的位置
上述后面两个步骤可以整合到一起,寻找合适位置的时候,同时完成元素的移动;
template <typename T>
void insertionSort(vector &nums) {
for(size_t i = 1; i < nums.size(); i++) {
T key = nums[i];
int j = i - 1;
while(j >= 0 && key < nums[j]) {
nums[j+1] = nums[j];
j--;
}
nums[j+1] = key;
}
}
代码第6行while
循环就是在寻找元素key对应的位置,如果位置不对,就把元素后移一位(第7行),j递减之后继续循环,直到找到对应的位置,此时将key放在对应的位置;