#include <iostream>
#include <vector>
#include <iterator>
using namespace std;
struct ListNode{
int val;
ListNode *left;
ListNode *right;
explicit ListNode(int x): val(x), left(nullptr), right(nullptr) {}
};
ListNode* buildFullTree(std::vector<int> &nums){
///* 构建完全二叉树
std::vector<ListNode*> nodes;
nodes.reserve(nums.size());
for(int num : nums){
nodes.emplace_back(new ListNode(num));
}
int n = nums.size();
for(int i=0; i<=n/2; i++){
if(2*i+1 <= n){
nodes[i]->left = nodes[2*i+1];
}
if(2*i+2 <= n){
nodes[i]->right = nodes[2*i+2];
}
}
return nodes[0];
}
///* 注1:
/// 对于具有n个结点的完全二叉树,
/// 起始节点从0编号时,筛选开始的结点为第 ⌊n/2⌋-1个结点,
/// 起始节点从1编号时,筛选开始的结点为第 ⌊n/2⌋个结点(此结点后序都是叶子结点,无需筛选)
void heapMinAdjust(std::vector<int> &nums, int i, int n){ ///* 构建小顶堆
int l = 2*i + 1;
int r = 2*i + 2;
if(l < n && nums[l] < nums[i]){
/// 加入此判断是为了保持稳定性,保证父节点只与两个子节点中较小的一个进行交换
/// r>=n, 表示不存在右子节点,可认为右子节点值小于左子节点
if((r>=n) || (r < n && nums[l] <= nums[r])){
std::swap(nums[i], nums[l]);
heapMinAdjust(nums, l, n);
}
}
if(r < n && nums[r] < nums[i]){
if(nums[l] > nums[r]){ // r<n意味着l<n一定成立
std::swap(nums[i], nums[r]);
heapMinAdjust(nums, r, n);
}
}
}
void heapMaxSort(std::vector<int> &nums){
ListNode* root = nullptr;
for(int k=0; k<nums.size(); k++){
int n = int(nums.size()) - k;
int t = n/2 - 1; ///* (n/2-1),见注1.
for(int i=t; i>=0; i--){
heapMinAdjust(nums, i, n);
}
std::swap(nums[0], nums[n-1]); //将最值放到最后,方便索引值的计算(关键一步,就地排序)
}
root = buildFullTree(nums);
}
void heapMaxAdjust(std::vector<int> &nums, int i, int n){ ///* 构建大顶堆
int l = 2*i + 1;
int r = 2*i + 2;
if(l < n && nums[l] > nums[i]){
/// 加入此判断是为了保持稳定性,保证父节点只与两个子节点中较小的一个进行交换
/// r>=n, 表示不存在右子节点,可认为右子节点值小于左子节点
if((r>=n) || (r < n && nums[l] > nums[r])){
std::swap(nums[i], nums[l]);
heapMaxAdjust(nums, l, n);
}
}
if(r < n && nums[r] > nums[i]){
if(nums[l] <= nums[r]){ // r<n意味着l<n一定成立
std::swap(nums[i], nums[r]);
heapMaxAdjust(nums, r, n);
}
}
}
void heapMinSort(std::vector<int> &nums){
ListNode* root = nullptr;
for(int k=0; k<nums.size(); k++){
int n = int(nums.size()) - k;
int t = n/2 - 1; ///* (n/2-1),见注1.
for(int i=t; i>=0; i--){
heapMaxAdjust(nums, i, n);
}
std::swap(nums[0], nums[n-1]); //将最值放到最后,方便索引值的计算
}
root = buildFullTree(nums);
}
int main(){
std::vector<int> nums {49, 38, 65, 97, 76, 13, 27, 49};
heapMaxSort(nums);
std::copy(nums.begin(), nums.end(), std::ostream_iterator<int>{std::cout, " "});
return 0;
}
/*
1(i)
/ \
2(2i) 3(2i+1)
/ \ / \
4 5 6 7
/ \ / \ / \ / \
8 9 10 11 12 13 14 15
0(i)
/ \
1(2i+1) 2(2i+2)
/ \ / \
3 4 5 6
/ \ / \ / \ / \
7 8 9 10 11 12 13 14
* */
堆排序 C++实现
最新推荐文章于 2024-07-04 16:16:29 发布