#include <iostream>
using namespace std;
#include <vector>
//调整数组v以i位置为根的子树为小根堆,数组堆的范围0到k-1
void HeadAdjustDown(vector<int>& v, int i, int k);
//对前k个元素建立小根堆
void BuildMinHeap(vector<int>& v, int k);
//取最小k个数
void GetLeastNumbers_Solution(vector<int>& input, int k);
//调整数组v以i位置为根的子树为大根堆,数组堆的范围0到k-1
void HeadAdjustUp(vector<int>& v, int i, int k);
//对前k个元素建立大根堆
void BuildMaxHeap(vector<int>& v, int k);
//取最大k个数
void GetMostNumbers_Solution(vector<int>& input, int k);
//堆排序从小到大
void MinHeapSort(vector<int>& v);
//堆排序从大到小
void MaxHeapSort(vector<int>& v);
int main() {
vector<int> v;
v.push_back(53);
v.push_back(17);
v.push_back(78);
v.push_back(9);
v.push_back(45);
v.push_back(65);
v.push_back(87);
v.push_back(32);
int k = 8;
cout << "这是原始数组:";
for (auto& a : v) {
cout << a << " ";
}
cout << endl;
GetLeastNumbers_Solution(v,5);
GetMostNumbers_Solution(v,5);
MaxHeapSort(v);
MinHeapSort(v);
return 0;
}
//调整数组v以i位置为根的子树为小根堆,数组堆的范围0到k-1
void HeadAdjustDown(vector<int>& v, int i, int k) {
int tmp = v[i];
//调整v[i]节点为根的子树,v[i]的左右孩子为v[2i+1]和v[2i+2]
for (int j = 2 * i + 1; j < k; j = 2 * j + 1) {
if (j + 1 < k && v[j] > v[j + 1]) {
//在右孩子存在的情况下
//左孩子小,j就已经指向左孩子
//右孩子小,那么让j指向右孩子,也就是j++
j++;
}
if (tmp < v[j])
break;//根节点本来就比左右孩子小
else {
v[i] = v[j]; //左右孩子中最小的数往上提
i = j; //让i指向它的左右孩子中最小的
}
}
v[i] = tmp;
}
//对前k个元素建立小根堆
void BuildMinHeap(vector<int>& v,int k) {
//前k个数下标0到k-1 最后一个非叶子节点下标是(k - 1)/2
for (int i = (k - 1) / 2; i >= 0; i--) {
//从最后一个非叶子节点开始逐个调整建立小根堆
HeadAdjustDown(v, i, k);
}
}
//取最小k个数
void GetLeastNumbers_Solution(vector<int>& input, int k) {
BuildMaxHeap(input, k);
for (int i = k; i < input.size(); i++) {
if (input[i] >= input[0])
continue;
else {
int tmp = input[0];
input[0] = input[i];
input[i] = tmp;
HeadAdjustUp(input, 0, k);
}
}
vector<int> v;
for (int i = 0; i < k; i++) {
v.push_back(input[i]);
}
cout << "数组最小k个数:";
for (auto& a : v) {
cout << a << " ";
}
cout << endl;
}
//调整数组v以i位置为根的子树为大根堆,数组堆的范围0到k-1
void HeadAdjustUp(vector<int>& v, int i, int k) {
int tmp = v[i];
//调整v[i]节点为根的子树,v[i]的左右孩子为v[2i+1]和v[2i+2]
for (int j = 2 * i + 1; j < k; j = 2 * j + 1) {
if (j + 1 < k && v[j + 1] > v[j]) {
j++;
}
if (tmp > v[j])
break;
else {
v[i] = v[j];
i = j;
}
}
v[i] = tmp;
}
//对前k个元素建立大根堆
void BuildMaxHeap(vector<int>& v, int k) {
//前k个数下标0到k-1 最后一个非叶子节点下标是(k - 1)/2
for (int i = (k - 1) / 2; i >= 0; i--) {
//从最后一个非叶子节点开始逐个调整建立小根堆
HeadAdjustUp(v, i, k);
}
}
//取最大k个数
void GetMostNumbers_Solution(vector<int>& input, int k) {
BuildMinHeap(input, k);
for (int i = k; i < input.size(); i++) {
if (input[i] <= input[0])
continue;
else {
int tmp = input[0];
input[0] = input[i];
input[i] = tmp;
HeadAdjustDown(input, 0, k);
}
}
vector<int> v;
for (int i = 0; i < k; i++) {
v.push_back(input[i]);
}
cout << "数组最大k个数:";
for (auto& a : v) {
cout << a << " ";
}
cout << endl;
}
//堆排序从小到大
void MinHeapSort(vector<int>& v) {
int len = v.size();
while (len) {
BuildMaxHeap(v, len);
swap(v[0], v[len-1]);
len--;
}
cout << "堆排序从小到大:";
for (auto& a : v) {
cout << a << " ";
}
cout << endl;
}
//堆排序从大到小
void MaxHeapSort(vector<int>& v) {
int len = v.size();
while (len) {
BuildMinHeap(v, len);
swap(v[0], v[len-1]);
len--;
}
cout << "堆排序从大到小:";
for (auto& a : v) {
cout << a << " ";
}
cout << endl;
}