插入排序算法

  插入排序(Insertion Sort)一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法 。插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表。在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动 。

  插入排序是指在待排序的元素中,假设前面n-1(其中n>=2)个数已经是排好顺序的,现将第n个数插到前面已经排好的序列中,然后找到合适自己的位置,使得插入第n个数的这个序列也是排好顺序的。按照此法对所有元素进行插入,直到整个序列排为有序的过程,称为插入排序。

  例如: 使用插入排序算法将数组 { 4,2,8,0,5,7,1,3,6,9 } 进行升序排序。

在这里插入图片描述
  实现代码如下所示。

#include<iostream>
using namespace std;

template<class T>
void InsertionSort(T *a, int n)
{
	int in, out;  //in排好顺序的;out未排好顺序的
	for (out = 1; out < n;out++)  //out = 0已经默认为排好顺序的
	{
		T temp = a[out];  //将待插入元素复制为哨兵
		in = out;
		while (in > 0 && a[in - 1] >= temp)  //从后往前查找待插入的位置
		{
			a[in] = a[in - 1];  //往后挪位置
			in--;
		}
		a[in] = temp;  //复制待插入元素到插入位置
	}
}

int main()
{
	int a[] = { 4,2,8,0,5,7,1,3,6,9 };

	cout << "排序前:" << endl;
	for (int i = 0; i < 10; i++)
	{
		cout << a[i] << "  ";
	}
	cout << endl;

	InsertionSort(a, 10);

	cout << "排序后:" << endl;
	for (int i = 0; i < 10; i++)
	{
		cout << a[i] << "  ";
	}
	cout << endl;

	double b[] = { 4.1,2.2,8.3,0.4,5.5,7.6,1.7,3.8,6.9,9.0 };

	cout << "排序前:" << endl;
	for (int i = 0; i < 10; i++)
	{
		cout << b[i] << "  ";
	}
	cout << endl;

	InsertionSort(b, 10);

	cout << "排序后:" << endl;
	for (int i = 0; i < 10; i++)
	{
		cout << b[i] << "  ";
	}
	cout << endl;

	system("pause");

	return 0;
}

排序前:
4 2 8 0 5 7 1 3 6 9
排序后:
0 1 2 3 4 5 6 7 8 9
排序前:
4.1 2.2 8.3 0.4 5.5 7.6 1.7 3.8 6.9 9
排序后:
0.4 1.7 2.2 3.8 4.1 5.5 6.9 7.6 8.3 9

  插入排序算法的详细过程如下图所示。

在这里插入图片描述

  时间复杂度: 对于长度为 n n n的数组,代码执行的时间都花费在最内层while循环里面的操作上(比较和移动)了。对于 n n n个元素,首先外层for循环要循环 n − 1 n-1 n1 次,然后内层while循环的循环次数是根据 i n in in来决定的, i n = 1 in = 1 in=1时循环 1 次, i n = 2 in = 2 in=2时循环 2 次,…, i n = n − 1 in = n-1 in=n1时循环 n − 1 n-1 n1 次,则总的代码执行次数为 1 + 2 + . . . + ( n − 1 ) = n ( n − 1 ) 2 = 1 2 n 2 − 1 2 n 1+2+...+(n-1)=\frac{n(n-1)}{2}=\frac{1}{2}n^{2}-\frac{1}{2}n 1+2+...+(n1)=2n(n1)=21n221n。根据复杂度计算规则,保留高阶项,并去掉系数,那么插入排序算法的时间复杂度为 O ( n 2 ) O(n^2) O(n2)

  空间复杂度: O ( 1 ) O(1) O(1)

  稳定性: 由于在比较的时候,对于两个相等的元素,不会进行移动,排序完成后,相同元素之间的先后顺序不变,所以插入排序是稳定的排序,如下图所示。

在这里插入图片描述
  优化插入排序算法: 对while循环的条件进行简化,以加快代码运行速度,并将插入排序函数分开编写。

  对于上述例子,优化实现代码如下所示。

#include<iostream>
using namespace std;

template<class T>
void Insertion(const T &temp, T *a, int j)
{
	a[0] = temp;
	//int j = i - 1;
	while (temp < a[j])  //使用a[0]设置条件,将之前版本的(in > 0 && a[in - 1] >= temp)条件进行简化,加快代码运行速度,j=0时a[j]=a[0]=temp,不满足条件,退出循环
	{
		a[j + 1] = a[j];
		j--;
	}
	a[j + 1] = temp;
}

template<class T>
void InsertionSort(T *a, int n)
{
	//a[0]用来保存排序使用,不能保存原始数据
	for (int i = 2; i <= n; i++)
	{
		T temp = a[i];
		Insertion(temp, a, i - 1);
		//a[0] = temp;
		//int j = i - 1;
		//while (temp < a[j])  //使用a[0]设置条件,将之前版本的(in > 0 && a[in - 1] >= temp)条件进行简化,加快代码运行速度,j=0时a[j]=a[0]=temp,不满足条件,退出循环
		//{
		//	a[j + 1] = a[j];
		//	j--;
		//}
		//a[j + 1] = temp;
	}
}

int main()
{
	int a[] = { 0,4,2,8,0,5,7,1,3,6,9 };  //在数组前面多加一个0,用于退出循环的条件

	cout << "排序前:" << endl;
	for (int i = 1; i < 11; i++)
	{
		cout << a[i] << "  ";
	}
	cout << endl;

	InsertionSort(a, 10);

	cout << "排序后:" << endl;
	for (int i = 1; i < 11; i++)
	{
		cout << a[i] << "  ";
	}
	cout << endl;

	double b[] = { 0,4.1,2.2,8.3,0.4,5.5,7.6,1.7,3.8,6.9,9.0 };

	cout << "排序前:" << endl;
	for (int i = 1; i < 11; i++)
	{
		cout << b[i] << "  ";
	}
	cout << endl;

	InsertionSort(b, 10);

	cout << "排序后:" << endl;
	for (int i = 1; i < 11; i++)
	{
		cout << b[i] << "  ";
	}
	cout << endl;

	system("pause");

	return 0;
}

排序前:
4 2 8 0 5 7 1 3 6 9
排序后:
0 1 2 3 4 5 6 7 8 9
排序前:
4.1 2.2 8.3 0.4 5.5 7.6 1.7 3.8 6.9 9
排序后:
0.4 1.7 2.2 3.8 4.1 5.5 6.9 7.6 8.3 9

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值