选择类排序

1.简介

选择类排序:即在排序过程中,选择最值关键字,然后与当前位置的关键字进行交换

2.简单选择排序

2.1 思想

每趟比较选择最小的关键字,然后将其放到当前遍历的位置

例如:待排序序列为{4,  2,  6,  9,  5,  1,  10,  3,  8,  7}

第1趟:1,  2,  6,  9,  5,  4,  10,  3,  8,  7      当前关键字为4,最小关键字为1

第2趟:1,  2,  6,  9,  5,  4,  10,  3,  8,  7      当前关键字为2,最小关键字为2

第3趟:1,  2,  3,  9,  5,  4,  10,  6,  8,  7      当前关键字为6,最小关键字为3

第4趟:1,  2,  3,  4,  5,  9,  10,  6,  8,  7      当前关键字为9,最小关键字为4

第5趟:1,  2,  3,  4,  5,  9,  10,  6,  8,  7      当前关键字为5,最小关键字为5

第6趟:1,  2,  3,  4,  5,  6,  10,  9,  8,  7      当前关键字为9,最小关键字为6

第7趟:1,  2,  3,  4,  5,  6,  7,  9,  8,  10      当前关键字为10,最小关键字为7

第8趟:1,  2,  3,  4,  5,  6,  7,  89,  10      当前关键字为9,最小关键字为8

第9趟:1,  2,  3,  4,  5,  6,  7,  8,  9,  10      当前关键字为9,最小关键字为9

第10趟:1,  2,  3,  4,  5,  6,  7,  8,  9,  10    当前关键字为10,最小关键字为10

2.2 实现

void select_sort(vector<int>& nums) //简单选择排序
{
	for (int i = 0; i < nums.size(); ++i) {
		int k = i;
		for (int j = i + 1; j < nums.size(); ++j) { //选择当前序列最小的元素
			if (nums[j] < nums[k]) {
				k = j;
			}
		}
		if (k != i) swap(nums[i], nums[k]);
	}
}

2.3 时间和空间复杂度分析

时间复杂度:排序趟数与初始序列无关,需比较的次数始终为(1+2+3+...+n) = n*(n-1) / 2,故最好和最坏时间复杂度都是O(n^2),最终平均时间复杂度为O(n^2).

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

3.堆排序

堆:是一种完全二叉树的结构,适合用顺序结构进行存储,父节点的索引若为i,则左孩子的索引为(i*2),右孩子的索引为(2*i+1).

3.1 思想

建堆,然后取堆顶节点,不断重复上述过程,直到当前堆只有一个节点

例如:待排序序列为{4,  2,  6,  9,  5,  1,  10,  3,  8,  7}

建堆:10,  9,  6,  8,  7,  1,  4,  3,  2,  5      取堆顶:5,  9,  6,  8,  7,  1,  4,  3,  2,  10

建堆:9,  8,  6,  5,  7,  1,  4,  3,  2,  10      取堆顶:2,  8,  6,  5,  7,  1,  4,  3,  9,  10

建堆:8,  7,  6,  5,  2,  1,  4,  3,  9,  10      取堆顶:3,  7,  6,  5,  2,  1,  4,  8,  9,  10 

建堆:7,  5,  6,  3,  2,  1,  4,  8,  9,  10      取堆顶:4,  5,  6,  3,  2,  1,  7,  8,  9,  10 

建堆:6,  5,  4,  3,  2,  1,  7,  8,  9,  10      取堆顶:1,  5,  4,  3,  2,  6,  7,  8,  9,  10

建堆:5,  3,  4,  2,  1,  6,  7,  8,  9,  10      取堆顶:1,  3,  4,  2,  5,  6,  7,  8,  9,  10 

建堆:4,  3,  1,  2,  5,  6,  7,  8,  9,  10      取堆顶:2,  3,  1,  4,  5,  6,  7,  8,  9,  10

建堆:3,  2,  1,  4,  5,  6,  7,  8,  9,  10      取堆顶:1,  2,  3,  4,  5,  6,  7,  8,  9,  10

建堆:2,  1,  3,  4,  5,  6,  7,  8,  9,  10      取堆顶:1,  2,  3,  4,  5,  6,  7,  8,  9,  10

3.2 实现 

void adjust_heap(vector<int>& nums, int pos, int endPos) //调整堆
{
	while (pos * 2 <= endPos) { //依次往下调整堆
		int temp = nums[pos * 2];
		if (pos * 2 + 1 <= endPos) temp = max(temp, nums[pos * 2 + 1]);
		if (nums[pos] >= temp) break;
		swap(nums[pos], temp);
		pos = nums[pos * 2] == nums[pos] ? pos * 2 : pos * 2 + 1; 	
		nums[pos] = temp;
	}
}

void heap_sort(vector<int>& nums) //堆排序
{
	for (int i = nums.size() / 2; i >= 1; --i) { //建堆
		adjust_heap(nums, i, nums.size() - 1);
	}

	for (int i = 1; i < nums.size() - 1; ++i) { //排序
		swap(nums[1], nums[nums.size() - i]);
		adjust_heap(nums, 1, nums.size() - i - 1);
	}
}

3.3 时间和空间复杂度分析

时间复杂度:堆排序类似于树的建立过程,时间复杂度为O(nlog2(n))

空间复杂度:O(1)

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

[2]数据结构高分笔记

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值