• 一个堆的c++实现


    关于堆的描述可以参考:

    http://www.cs.auckland.ac.nz/~jmor159/PLDS210/heaps.html

    我的实现没有用二叉树,而是用数组。上文提到,由于堆是一种complete树(complete,和完全树略有区别),即子节点的上层是完全树,而子节点从左向右严格排列,这种数据结构可以用数组很好模拟。从第一层第一个节点为1开始,从左到右从上到下依次存储。则,对于某个索引为i的节点,其左子节点和右子节点的索引分别为:

    i * 2, i * 2 + 1

    C++代码:

    #include <iostream>
    
    using namespace std;
    
    template<class T>
    class doubleHeap
    {
    public:
        doubleHeap(
            int _size,
            int _type // 1 : max heap 2 : min heap
            );
        void extractTop(T &top);
        void deleteTop();
        bool addElement(T _new_element);
        bool empty();
        bool full();
        void printHeap(int root, int level); // for debug
    
    private:
        void swap(int i, int j);
        int leftChild(int i);
        int rightChild(int i);
        int parent(int i);
        bool comp(int i, int j); // if the nodes should exchange
    
    private:
        T *data;
        int max_size;
        int size;
        int type;
    };
    
    template<class T>
    doubleHeap<T>::doubleHeap(int _size, int _type)
    {
        max_size = 10;
        if(_size >= 10)
            max_size = _size;
        data = new T[max_size];
        size = 0;
        type = 1; // default max heap
        if(_type == 1 || type == 2)
            type = _type;
    }
    
    template<class T>
    void doubleHeap<T>::extractTop(T &top)
    {
        if(size == 0)
            return;
    
        top = data[0];
    }
    
    template<class T>
    void doubleHeap<T>::deleteTop()
    {
        if(size == 0)
            return;
    
        data[0] = data[size - 1];
        size --;
    
        int cur = 0; // start from the root
        int lChildIndex;
        int rChildIndex;
    
        // begin exchanging the node and check if it's been a heap
        while(true)
        {
            if(cur >= size) // the heap is null
                break;
    
            rChildIndex = rightChild(cur);
            lChildIndex = leftChild(cur);
    
            if(lChildIndex >= size) // right child and left child has been a null
                break;
            else if(rChildIndex >= size) // rightChild null, left not
            {
                if(comp(cur, lChildIndex))
                {
                    swap(cur, lChildIndex);
                    cur = lChildIndex;
                }
                else
                    break; // has been a heap
            }
            else // left and right are not null
            {
                if(comp(cur, rChildIndex) || comp(cur, lChildIndex))
                {
                    if(comp(lChildIndex, rChildIndex))
                    {
                        swap(cur, rChildIndex);
                        cur = rChildIndex;
                    }
                    else
                    {
                        swap(cur, lChildIndex);
                        cur = lChildIndex;
                    }
                }
                else
                    break;
            }
        }
    }
    
    template<class T>
    bool doubleHeap<T>::addElement(T _new_element)
    {
        data[size] = _new_element;
        size ++;
    
        int cur = size - 1;
        int parentIndex;
        while(true)
        {
            if(cur == 0)
                break;
    
            parentIndex = parent(cur);
            if(comp(parentIndex, cur))
            {
                swap(cur, parentIndex);
                cur = parentIndex;
            }
            else
                break;
        }
    }
    
    template<class T>
    bool doubleHeap<T>::empty()
    {
        return size == 0;
    }
    
    template<class T>
    bool doubleHeap<T>::full()
    {
        return max_size == size;
    }
    
    template<class T>
    void doubleHeap<T>::swap(int i, int j)
    {
        T ex;
        ex = data[i];
        data[i] = data[j];
        data[j] = ex;
    }
    
    template<class T>
    int doubleHeap<T>::leftChild(int i)
    {
        return 2 * (i + 1) - 1;
    }
    
    template<class T>
    int doubleHeap<T>::rightChild(int i)
    {
        return 2 * (i + 1);
    }
    
    template<class T>
    int doubleHeap<T>::parent(int i)
    {
        return (i + i) / 2 - 1;
    }
    
    template<class T>
    bool doubleHeap<T>::comp(int i, int j)
    {
        if(type == 1) // max heap
        {
            return data[i] < data[j];
        }
        else // min heap
        {
            return data[i] > data[j];
        }
    }
    
    template<class T>
    void doubleHeap<T>::printHeap(int root, int level)
    {
        int i;
    
        if(root >= size)
            return;
    
        printHeap(leftChild(root), level + 1);
        for(i = 0; i < level; i ++)
            cout << "\t";
        cout << data[root] << endl;
        printHeap(rightChild(root), level + 1);
    }
    
    int main()
    {
        int a[] = {1, 10, 6, 23, 7, 8, 90, 12, 45, 76, 33, 25, 3, 17, 70, 10};
        int i, aLen = 16, e;
        doubleHeap<int> maxHeap(100, 1);
    
        for(i = 0; i < aLen; i ++)
        {
            maxHeap.addElement(a[i]);
        }
    
        maxHeap.printHeap(0, 0);
    
        // heap sort
        while(!maxHeap.empty())
        {
            maxHeap.extractTop(e);
            cout << e << " ";
            maxHeap.deleteTop();
        }
    
        return 0;
    }

    输出:

                                    1
                            17
                    45
                            12
            76
                            10
                    33
                            10
    90
                            8
                    25
                            7
            70
                            6
                    23
                            3
    90 76 70 45 33 25 23 17 12 10 10 8 7 6 3 1

    ____________________________
    本博客文章主要供博主学习交流用,所有描述、代码无法保证准确性,如有问题可以留言共同讨论。
  • 相关阅读:
    bzoj3007: 拯救小云公主
    bzoj4316: 小C的独立集
    PostgreSQL Replication之第三章 理解即时恢复(3)
    PostgreSQL Replication之第三章 理解即时恢复(2)
    PostgreSQL Replication之第三章 理解即时恢复(1)
    PostgreSQL Replication之第二章 理解PostgreSQL的事务日志(5)
    PostgreSQL Replication之第二章 理解PostgreSQL的事务日志(4)
    PostgreSQL Replication之第二章 理解PostgreSQL的事务日志(3)
    PostgreSQL Replication之第二章 理解PostgreSQL的事务日志(2)
    PostgreSQL Replication之第二章 理解PostgreSQL的事务日志(1)
  • 原文地址:https://www.cnblogs.com/waytofall/p/2440722.html
Copyright © 2020-2023  润新知