选择排序(SlectionSort)
相关概念
- 在使用两个for循环的情况下,选择排序的平均时间复杂度为O(N^2)
实现描述
1、实现思想
template<typename T>
void SelectionSort(vector<T>& vec) {
for (int i = 0; i < vec.size(); ++i) {
// 从i到容器末尾找最小元,并返回位置。如果直接使用for循环将使时间复杂度到达O(N^2)
int minPos = ScanForMin(vec, i);
// 将未排序的最小元和目前的i进行交换,则i之前的位置都是有序部分
std::swap(vec[i], vec[minPos]);
}
}
2、简单实现
template<typename T>
void SelectionSort(vector<T>& vec) {
for (int i = 0; i < vec.size(); ++i) {
int minPos = i;
for (int j = i; j < vec.size(); j++) {
minPos = vec[j] < vec[minPos] ? j : minPos;
}
std::swap(vec[i], vec[minPos]);
}
}
堆排序(HeapSort)
参考链接:https://www.cnblogs.com/chengxiao/p/6129630.html
相关概念
- 堆排序是一种选择排序,它的最好、最坏、平均时间复杂度均为O(nlogn);同时堆排序也是不稳定排序
- 堆是一个完全二叉树,某一节点的值总是不大于或不小于其它孩子节点的值
- 堆的每个节点的子树都是堆
- 以最大堆进行选择排序为例,由于根节点的值是最大的,每次取出最大值,剩余的再建堆,再取出最大值,以此循环(为什么不取剩下左右子节点的值?因为左右节点的值中有一个肯定是最大值,但另一个就不一定是最大值了)
- 如果使用最小堆进行排序,那么就需要额外的O(N)的空间,并不是最好的方式
实现描述
template<typename T>
void AdjustHeap(vector<T>& vec, int i, int length) {
T tmp = vec[i]; // 先取出当前元素i
// 从i结点的左子结点开始,也就是2i+1处开始
for (int k = i * 2 + 1; k < length; k = 2 * k + 1) {
// 如果左子结点小于右子结点,k指向右子结点
if (k + 1 < length && vec[k] < vec[k + 1])
k++;
if (vec[k] > tmp) { // 如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
vec[i] = vec[k];
i = k;
}
else
break;
}
vec[i] = tmp; // 将tmp值放到最终的位置
}
template<typename T>
void HeapSort(vector<T>& vec) {
// 构建最大堆
for (int i = vec.size() / 2 - 1; i >= 0; i--) {
AdjustHeap(vec, i, vec.size());
}
// 调整堆结构+交换堆顶元素与末尾元素
for (int j = vec.size() - 1; j > 0; j--) {
std::swap(vec[0], vec[j]);
AdjustHeap(vec, 0, j);
}
}