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, 8, 9, 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]数据结构高分笔记