**插入排序:**每一趟将一个待排序的记录,按照其关键字的大小插入到有序队列的合适位置里,直到全部插入完成。
动图如下:
从下标为1的元素开始,将其与其之前的元素进行大小比较,如果之前的元素比他小,那么就直接插入到该元素的后边,反之,则继续向前比较,直到找到比需插入元素小的元素位置进行插入,或者一直遍历到数组开头都没发现比需要插入的元素小的,那就直接插入到数组的最前端,每一个元素都按照这样的方法,直到所有元素全部插入完成。
代码如下:
#include <iostream>
#include <vector>
using namespace std;
vector<int> InsertSort(vector<int> list)
{
vector<int>result = list;
if (result.empty()) //判断容器内容是否为空
return result;
//第一个元素是有序的,所以从下标为1的元素开始
for (int i = 1; i < result.size(); i++)
{
int temp = result[i];
int j = i - 1;
//取出第i个元素,将其与之前的元素进行比较,
//直到找到比它小的元素或者遍历完所有元素将其放在开头
for (j; j >= 0 && result[j] > temp; j--)
{
result[j + 1] = result[j];
}
result[j + 1] = temp;
}
return result;
}
int main()
{
int arr[] = { 5, 2, 3, 78, 54, 9, 15, 20 };
vector<int>test(arr, arr + sizeof(arr) / sizeof(arr[0]));
cout << "排序前:" << endl;
for (int i = 0; i < test.size(); i++)
{
cout << test[i] << " ";
}
cout << endl;
vector<int>result = InsertSort(test);
cout << "排序后:" << endl;
for (int j = 0; j < result.size(); j++)
{
cout << result[j] << " ";
}
cout << endl;
system("pause");
}
运行结果如下:
时间复杂度:
最好的情况:所有数据是正序,每次排序都不用移动元素,此时为O(N);
最坏的情况:所有数据都是倒序,每次都要将前面的元素后移,此时为O(N^2);
空间复杂度:
在排序的过程中,需要一个临时存储取出值的temp变量,所以空间复杂度为O(1);
直接插入排序是稳定的排序算法,因为它不需要改变相同元素的位置;
优化直接插入算法——折半插入算法
由上方排序算法可知,当在一个有序序列中插入元素的时候,可以使用二分查找法,减少元素之间的比较次数,以便提高算法的效率。
二分查找是对于有序数组而言的,假设如果数组是升序排序的。那么,二分查找算法就是不断对数组进行对半分割,每次拿中间元素和目标数字进行比较,如果中间元素小于目标数字,则说明目标数字应该在右侧被分割的数组中,如果中间元素大于目标数字,则说明目标数字应该在左侧被分割的数组中。
代码如下:
#include <iostream>
#include <vector>
using namespace std;
vector<int> BInsertSort(vector<int> list)
{
vector<int>result = list;
if (result.empty()) //判断是否为空
{
return result;
}
for (int i = 1; i < result.size(); i++) //依次插入下标为1-n的元素
{
int low = 0;
int high = i - 1; //采用二分查找法查找插入位置
int temp = result[i]; //取出待插入的元素
while (low <= high) //二分查找,找出有序数列中第一个大于等于待插入元素的下标
{
int mid = (low + high) / 2;
if (result[mid] > temp)
high = mid - 1;
else
low = mid + 1; //找到第一个大于等于待插入元素的元素下标位置为high+1;
}
for (int j = i - 1; j >= high + 1;j--) //将大于待插入元素的的元素都后移一位
{
result[j + 1] = result[j];
}
result[high + 1] = temp;
}
return result;
}
int main()
{
int arr[] = { 6, 4, 8, 9, 2, 3, 1 };
vector<int> test(arr, arr + sizeof(arr) / sizeof(arr[0]));
cout << "排序前:" << endl;
for (int i = 0; i < test.size(); i++)
{
cout << test[i] << " ";
}
cout << endl;
vector<int>result = BInsertSort(test);
cout << "排序后:" << endl;
for (int j = 0; j < result.size(); j++)
{
cout << result[j] << " ";
}
cout << endl;
system("pause");
}
运行结果如下:
参考:
https://cuijiahua.com/blog/2017/12/algorithm_2.html
https://blog.youkuaiyun.com/j4ya_/article/details/80729947