插入类排序

1.简介

插入类排序:顾名思意,即排序过程中,在有序的序列当中插入元素。分为以下三类

2.直接插入排序 

2.1 思想

逐个将第n个待排序元素添加到前(n-1)个有序序列当中。

例如:待排序序列为{4,  2,  6,  9,  5,  1,  10,  3,  8,  7},每次从右向左查找元素的插入位置

第1趟:4                   2,  6,  9,  5,  1,  10,  3,  8,  7     添加4                                                   

第2趟:2  4                    6,  9,  5,  1,  10,  3,  8,  7     添加2

第3趟:2  4   6                    9,  5,  1,  10,  3,  8,  7     添加6

第4趟:2  4   6   9                    5,  1,  10,  3,  8,  7      添加9

第5趟:2  4   5   6   9                    1,  10,  3,  8,  7      添加5

第6趟:1  2   4   5   6   9                     10,  3,  8,  7      添加1

第7趟:1  2   4   5   6   9   10                    3,  8,  7       添加10

第8趟:1  2   3   4   5   6   9   10                    8,  7       添加3

第9趟:1  2   3   4   5   6      9   10                   7       添加8

第10趟:1  2  3   4   5   6   7    8    9   10                     添加7

2.2 实现

void direct_insert_sort(vector<int>& nums)  
{
	for (int j = 1; j < nums.size(); ++j) {
		int temp = nums[j];
		int k = j-1;
		while (k >= 0  && nums[k] > temp) {  //查找插入位置
			nums[k+1] = nums[k];
			--k;
		}
		nums[k + 1] = temp; //填充插入元素
	}
}

2.3 时间和空间复杂度分析 

时间复杂度:若当前序列为有序序列,无需进行任何元素的移动,最好时间复杂度为O(n),最坏的情况为倒序的序列,需比较的次数为(1+2+3+...+n) = n*(n-1) / 2,故最坏时间复杂度为O(n^2),故最终的平均复杂度为O(n^2)

空间复杂度:除了一个临时交换变量的空间,无需任何额外的空间,故为O(1)

3.折半查找排序

3.1 思想

采用折半查找待排序元素在前(n-1)个元素有序序列的插入位置。

例如,待排序序列为{4,  2,  6,  9,  5,  1,  10,  3,  8,  7},每次折半查找元素的插入位置

第1趟:4                   2,  6,  9,  5,  1,  10,  3,  8,  7     添加4                                                      

第2趟:2  4                    6,  9,  5,  1,  10,  3,  8,  7     添加2   left = 0, right = 0--->插入位置0

第3趟:2  4   6                    9,  5,  1,  10,  3,  8,  7     添加6  left = 0, right = 1---->插入位置2

第4趟:2  4   6   9                    5,  1,  10,  3,  8,  7      添加9 left = 0, right = 2---->插入位置3

第5趟:2  4   5   6   9                    1,  10,  3,  8,  7      添加5

第6趟:1  2   4   5   6   9                     10,  3,  8,  7      添加1

第7趟:1  2   4   5   6   9   10                    3,  8,  7       添加10

第8趟:1  2   3   4   5   6   9   10                    8,  7       添加3

第9趟:1  2   3   4   5   6      9   10                   7       添加8

第10趟:1  2  3   4   5   6   7    8    9   10                     添加7

3.2 实现

void half_insert_sort(vector<int>& nums)
{
	for (int j = 1; j < nums.size(); ++j) {	
		int left = 0;
		int right = j - 1;
		int temp = nums[j];
		while (left <= right) { //折半查找插入位置
			int mid = (left + right) / 2;
			if (nums[mid] > temp) right = mid - 1;
			else left = mid + 1;
		}
		right = j - 1;
		while (right >= left) { //移动元素
			nums[right + 1] = nums[right];
			right--;
		}
		nums[left] = temp;
	}
}

3.3 时间和空间复杂度分析

时间复杂度:若当前序列为有序序列,每次只需查找一半,最好时间复杂度为O(n*log(n)),最坏的情况为倒序的序列,需比较的次数为(1+2+3+...+n) = n*(n-1) / 2,故最坏时间复杂度为O(n^2),故最终的平均复杂度为O(n^2)

空间复杂度:除了一个临时交换变量的空间,无需任何额外的空间,故为O(1)

4 希尔排序

4.1 思想

将待排序的序列按照增量分为待排序的子序列,依次缩小增量,重新划分子序列,......,直至增量大小为1,最终的序列即为有序序列.

例如:待排序序列为{4,  2,  6,  9,  5,  1,  10,  3,  8,  7},每次根据增量划分子序列

第1趟:增量为10 / 2 = 5

子序列1:4,                       1  

子序列2:     2,                       10

子序列3:           6,                         3

子序列4:                9,                         8

子序列5:                     5,                         7

合并子序列后:  1,  2,  3,  8,  5,  4,  10,  6,  9,  7

第2趟:增量为5 / 2 = 2

子序列1:1,       3,        5,       10,       9

子序列2:     2,        8,       4,         6,       7

排序后:  1,  2,  3,  4,  5,  6,  9,  7,  10,  8                                             

最后一趟后:1,  2,  3,  4,  5,  6,  7,  8,  9,  10    

4.2 实现

void different_dis_sort(vector<int>& nums, int start, int dis, int cur) 
{
	int t = nums[cur];
	cur -= dis;
	while (cur >= start && nums[cur] > t) { //局部的直接插入排序
		nums[cur + dis] = nums[cur];
		cur -= dis;
	}
	nums[cur + dis] = t;
}

void hill_insert_sort(vector<int>& nums)
{
	int dis = log2(nums.size() - 1);
	while (dis >= 1) {
		int start = 0;
		while (start < dis) {
			int cur = start + dis;
			while (cur < nums.size()) {
				different_dis_sort(nums, start, dis, cur);
				cur += dis;
			}
			start++; //下一个位置开始
		}
		//dis /= 2; //希尔增量
		dis = log2(dis); //帕和斯增量
		cout << dis << endl;
	}
}

4.3 时间和空间复杂度分析

时间复杂度:取决于增量的选取,若采用希尔增量(n/2),最终的时间复杂度为O(n^2);若采用papernov&Stasevich增量(log(n)),时间复杂度为O(n^1.5)

空间复杂度:除了一个临时交换变量的空间,无需任何额外的空间,故为O(1)

[1]数据结构清华大学版

[2]数据结构高分笔记

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值