一.算法概述
1. 算法分类
十种常见排序算法可以分为两大类:
非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此称为非线性时间比较类排序。
线性时间非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此称为线性时间非比较类排序
二.算法介绍
3.直接插入排序
从下标为1的元素开始,将其与其之前的元素进行大小比较,如果之前的元素比他小,那么就直接插入到该元素的后边,反之,则继续向前比较,直到找到比需插入元素小的元素位置进行插入,或者一直遍历到数组开头都没发现比需要插入的元素小的,那就直接插入到数组的最前端,每一个元素都按照这样的方法,直到所有元素全部插入完成。
//容易写错 i j那块
void charu(vector<int> &nums)
{
for (int i = 1; i < nums.size(); i++)//待插入数字
{
int j = i - 1;
int temp = nums[i];
for ( ; j >=0&& temp < nums[j]; j--)//正序排列
{
nums[j + 1] = nums[j];
}
j++;//因为退出的时候多加了一回
nums[j] = temp;
}
}
时间复杂度:
最好的情况:所有数据是正序,每次排序都不用移动元素,此时为O(N);
最坏的情况:所有数据都是倒序,每次都要将前面的元素后移,此时为O(N^2);
空间复杂度:
在排序的过程中,需要一个临时存储取出值的temp变量,所以空间复杂度为O(1);
直接插入排序是稳定的排序算法,因为它不需要改变相同元素的位置;
9.快速排序
快速排序是交换排序,其基本思想是
1.任取一个元素(如:第一个)为中心元素
2.所有比它小的元素一律前放,反之则后放,形成左右两个子表
3.对各子表重新选择中心元素并依此规则调整
4.直到每个子表的元素只剩一个
/*
二分的思想 选定第一个标定数,
数组前半部分小于标定后半部分大于标定
递归结束条件:数组为空或者子数组left>=right
*/
void kuaisu(vector<int>& nums, int left, int right)
{
if (nums.empty()||left>=right)
return ;
int base_index = left;
int base_num = nums[base_index];
int l = left, r = right;
while (l < r)
{
while (l < r)
{
if (nums[r] < base_num)
{
nums[l] = nums[r];
break;
}
r--;
}
while (l < r)
{
l++;
if (nums[l] > base_num)
{
nums[r] = nums[l];
break;
}
}
}
base_index = l;
nums[base_index] = base_num;
kuaisu(nums, left, base_index - 1);//左边
kuaisu(nums, base_index+1 , right);//右边
return;
}
在这里插入代码片
参考:
[1] C++经典排序算法总结
[2] 八大排序算法——专栏