#include<iostream>
#include<assert.h>
#include <time.h>
#include <cmath>
using namespace std;
template<typename Item>
class MaxHeap{
private:
Item* data;
int count;
int capacity;
void shiftUp(int k){
// k>1 代表最小是2, 只需要和1比较
while(k>1 && data[k/2] < data[k]){
swap(data[k/2],data[k]);
k/=2;
}
}
void shiftDown(int k){
// 需要有左孩子,但不一定有右边的孩子
while (2*k <= count)
{
int j = 2*k;
if (j+1<=count && data[j+1] > data[j]){
j += 1;
}
if (data[k] >= data[j]){
break;
}
swap(data[k],data[j]);
k = j;
}
}
void putNumberInLine( int num, string &line, int index_cur_level, int cur_tree_width, bool isLeft){
int sub_tree_width = (cur_tree_width - 1) / 2;
int offset = index_cur_level * (cur_tree_width+1) + sub_tree_width;
assert(offset + 1 < line.size());
if( num >= 10 ) {
line[offset + 0] = '0' + num / 10;
line[offset + 1] = '0' + num % 10;
}
else{
if( isLeft)
line[offset + 0] = '0' + num;
else
line[offset + 1] = '0' + num;
}
}
void putBranchInLine( string &line, int index_cur_level, int cur_tree_width){
int sub_tree_width = (cur_tree_width - 1) / 2;
int sub_sub_tree_width = (sub_tree_width - 1) / 2;
int offset_left = index_cur_level * (cur_tree_width+1) + sub_sub_tree_width;
assert( offset_left + 1 < line.size() );
int offset_right = index_cur_level * (cur_tree_width+1) + sub_tree_width + 1 + sub_sub_tree_width;
assert( offset_right < line.size() );
line[offset_left + 1] = '/';
line[offset_right + 0] = '\\';
}
public:
MaxHeap(int capacity){
// 构造函数,开辟空间
data = new Item[capacity + 1];
count = 0;
this->capacity = capacity;
}
~MaxHeap(){
// 析构函数,释放空间
delete[] data;
}
// 因为两个变量是私有的,所以要用方法来搞它
bool isEmpty(){
return count == 0;
}
// 获取有多少个元素
int size(){
return count;
}
// 入队操作
void insert(Item item){
assert(count+1<=capacity);
// @todo 一旦发现不能容纳, 就扩容
data[count+1] = item;
count++;
shiftUp(count);
}
// 出队操作,出队最大的元素,然后把整个数组最后一个元素,放到数组最顶上。
Item extractMax(){
assert(count > 0);
Item ret = data[1];
swap(data[1], data[count]);
count--;
shiftDown(1);
return ret;
}
// 以树状打印整个堆结构
void testPrint(){
// 我们的testPrint只能打印100个元素以内的堆的树状信息
if( size() >= 100 ){
cout<<"This print function can only work for less than 100 int";
return;
}
// 我们的testPrint只能处理整数信息
if( typeid(Item) != typeid(int) ){
cout <<"This print function can only work for int item";
return;
}
cout<<"The max heap size is: "<<size()<<endl;
cout<<"Data in the max heap: ";
for( int i = 1 ; i <= size() ; i ++ ){
// 我们的testPrint要求堆中的所有整数在[0, 100)的范围内
assert( data[i] >= 0 && data[i] < 100 );
cout<<data[i]<<" ";
}
cout<<endl;
cout<<endl;
int n = size();
int max_level = 0;
int number_per_level = 1;
while( n > 0 ) {
max_level += 1;
n -= number_per_level;
number_per_level *= 2;
}
int max_level_number = int(pow(2, max_level-1));
int cur_tree_max_level_number = max_level_number;
int index = 1;
for( int level = 0 ; level < max_level ; level ++ ){
string line1 = string(max_level_number*3-1, ' ');
int cur_level_number = min(count-int(pow(2,level))+1,int(pow(2,level)));
bool isLeft = true;
for( int index_cur_level = 0 ; index_cur_level < cur_level_number ; index ++ , index_cur_level ++ ){
putNumberInLine( data[index] , line1 , index_cur_level , cur_tree_max_level_number*3-1 , isLeft );
isLeft = !isLeft;
}
cout<<line1<<endl;
if( level == max_level - 1 )
break;
string line2 = string(max_level_number*3-1, ' ');
for( int index_cur_level = 0 ; index_cur_level < cur_level_number ; index_cur_level ++ )
putBranchInLine( line2 , index_cur_level , cur_tree_max_level_number*3-1 );
cout<<line2<<endl;
cur_tree_max_level_number /= 2;
}
}
};
int main(){
MaxHeap<int> maxHeap = MaxHeap<int>(100);
cout << maxHeap.size() << endl;
srand(time(NULL));
for( int i = 0; i< 50; i++){
maxHeap.insert(rand()%100);
}
maxHeap.testPrint();
while (!maxHeap.isEmpty()){
cout << maxHeap.extractMax() << " ";
}
cout << endl;
return 0;
}
【数据结构与算法】C++ 维护一个最大堆
猜你喜欢
转载自blog.csdn.net/weixin_40293999/article/details/132708606
今日推荐
周排行