【数据结构与算法】C++ 维护一个最大堆

#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;
}

猜你喜欢

转载自blog.csdn.net/weixin_40293999/article/details/132708606
今日推荐