C++实现排序算法之直接插入排序

**插入排序:**每一趟将一个待排序的记录,按照其关键字的大小插入到有序队列的合适位置里,直到全部插入完成。
动图如下:
直接插入排序
从下标为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.csdn.net/j4ya_/article/details/80729947

  • 6
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值