数据结构-排序算法之插入排序

357 阅读3分钟
原文链接: milk2we.github.io

什么是插入排序

插入排序的基本思想是:每一趟将一个待排序的记录,按其关键字的大小插入到已经排好序的一组记录的合适位置上,直到所有的待排序记录全部插入为止。
根据查找的方法不同,有多种不同的排序方法,接下来将介绍三种方法:直接插入排序、折半排序、希尔排序。

直接插入排序


算法思想:

将记录插入到已经排好序的有序表中,从而得到一个新的、记录数量加一的有序表。基本的实现思想是:新增的数据和有序表中的最末尾的数据进行比较,如果记录小于有序表的最后一个记录,那么将这个记录存放在监视哨中,同时不断的比较前方数据 ,并且将比这个数据大的数据进行后移。当监视哨里面的数据发现了有序表中的数据不再比他大的时候间数据进行存放在后移所留下的空余位置。

算法过程实现

enter description here

直接插入

算法代码实现

具体的代码实现如下:

class InserSort {
public:
	void InsertSort (vector<int> &arry) {
	for (i = 2; i <= arry.size(); i++) {
		if (arry[i] < arry[i-1]) {
			arry[0] = arry[i];
			arry[i] = arry[i-1];
			for(j = i - 2; arry[0] < arry[j]; j--) 
				arry[j+1] = arry[j];
			arry[j+1] = arry[0];
		}
	}
}
private:
	int i;	
	int j;
};

算法分析

(1)时间复杂度:从时间来看,排序最基本的操作为:比较 两个关键字的大小和移动记录。时间复杂度为O(n2);
(2)空闲复杂度:直接插入只需要一个记录的辅助空间,所以 空格键复杂度为O(1);


折半插入排序


算法思想:

和直接插入类似,折半插入的方法是,按照折半查找的顺序来实现的,利用顺序摆的顺序,按照折半的方式进行查找,如果数据出现较小的话,那么就把high前移,反之则后移当出现low<=high的时候,就找到了数据最佳存在的位置,这样排序就实现了。

算法过程实现

和直接插入类似。

算法代码实现

class BInsertSort {
public:	
	void BInsertSorts (vector<int> &arry)  {
		for(i = 2; i < arry.size(); i++) {
			arry[0] = arry[i];
			low = 1; high = i-1;
			while(low<=high) {
				mid = (low + high) / 2;
				if (arry[0] < arry[mid]) high = mid - 1;
				else low = mid + 1;
			}
			for (j = i -1; j >= high+1; j--) arry[j+1] = arry[j];
			arry[high+1] = arry[0]; 
		}
	}
private:
	int i,j,low,high;
	int mid;
};

算法分析

(1)时间复杂度:从时间上来讲折半插入的速度比顺序查找块。在平均情况下,折半插入排序仅减少了关键字之间的比较次数,而记录的移动次数不变。因此,折半插入排序的算法复杂度仍然是O(n2)
(2)空间复杂度:和直接插入排序的空间复杂度相同。都是O(n2)。


希尔排序


算法思想:

希尔排序又称之为“缩小增量排序”,是插入排序的一种。
希尔排序的实质就是采用分组排序的方法。现将整个待排序的记录分隔成为几组,从而减少参与直接排序的数据量,对每一组的数据进行直接插入排序,然后增加没组的数据量,重新分组。这样当经过几次分组之后,整个序列中 的记录“基本有序”时,再对全体记录进行一次直接插入排序。

算法过程实现

enter description here

希尔排序

算法代码实现

class ShellInster {
public:
	void ShellInsters (vector<int> &arry, int dk) {
	 for (i = dk + 1; i < arry.size(); i++) {
	 	if (arry[i] < arry[i - dk]) {
	 		arry[0] = arry[i];
	 		for (j = i - dk; j > 0 && arry[0] < arry[j]; j-=dk) 
	 			arry[j + dk] = arry[j];
	 		arry[j + dk] = arry[0];
		 }
	 }
	}
	
private:
	int i,j;
	
};

class ShellSort {
public:
	void ShellSorts(vector<int> &arry) {
		m = arry.size()/2;
		while(m >= 1) {
			m=m/2;
			m1.ShellInsters(arry,m);
		}
	}

private:
	int m;
	ShellInster m1; 
};

算法分析

(1) 时间复杂度
时间复杂度减少到n(log2n²)
(2) 空间复杂度
也是O(1)