二叉树之哈弗曼树

实现哈弗曼树(后续实现哈弗曼编码)

1. MinHeap.h

/****************  MinHeap.h  **********************/
#include <iostream>
using namespace std;

#define FALSE 0
#define TRUE 1

template <class T>
class MinHeap                           //最小堆类定义
{
private:
    T* heapArray;                       //存放堆数据的数组
    int CurrentSize;                    //当前堆中元素数目
    int MaxSize;                        //堆所能容纳的最大元素数目
    void swap(int pos_x, int pos_y);    //交换位置x和y的元素
    void BuildHeap();                   //建堆
public:
    MinHeap(const int n);               //构造函数,n表示初始化堆的最大元素数目
    virtual ~MinHeap()
    {
        delete []heapArray;
    };     //析构函数
    bool isLeaf(int pos) const;         //如果是叶结点,返回TRUE
    int leftchild(int pos) const;       //返回左孩子位置
    int rightchild(int pos) const;      //返回右孩子位置
    int parent(int pos) const;          //返回父结点位置
    bool Remove(int pos, T& node);      //删除给定下标的元素
    bool Insert(const T& newNode);      //向堆中插入新元素newNode
    T& RemoveMin();                     //从堆顶删除最小值
    void SiftUp(int position);          //从position向上开始调整,使序列成为堆
    void SiftDown(int left);            //筛选法函数,参数left表示开始处理的数组下标
};
template<class T>
MinHeap<T>::MinHeap(const int n)
{
    if(n <= 0)
        return;
    CurrentSize = 0;
    MaxSize = n;                        //初始化堆容量为n
    heapArray = new T[MaxSize];         //创建堆空间
    //此处进行堆元素的赋值工作
    BuildHeap();
}
template<class T>
bool MinHeap<T>::isLeaf(int pos) const
{
    return (pos >= CurrentSize/2) && (pos < CurrentSize);
}

template<class T>
void MinHeap<T>::BuildHeap()
{
    for (int i = CurrentSize/2-1; i >= 0; i--)  //反复调用筛选函数
        SiftDown(i);
}

template<class T>
int MinHeap<T>::leftchild(int pos) const
{
    return 2*pos + 1;                           //返回左孩子位置
}

template<class T>
int MinHeap<T>::rightchild(int pos) const
{
    return 2*pos + 2;                           //返回右孩子位置
}

template<class T>
int MinHeap<T>::parent(int pos) const
{
    return (pos-1)/2;                           //返回父结点位置
}

template <class T>
bool MinHeap<T>::Insert(const T& newNode)       //向堆中插入新元素newNode
{
    if(CurrentSize == MaxSize)                  //堆空间已经满
        return FALSE;
    heapArray[CurrentSize] = newNode;
    SiftUp(CurrentSize);                        //向上调整
    CurrentSize++;
    return TRUE;
}

template<class T>
void MinHeap<T>::SiftUp(int position)   //从position向上开始调整,使序列成为堆
{
    int temppos = position;
    T temp = heapArray[temppos];
    while ((temppos>0) && (heapArray[parent(temppos)]>temp))
    {
        heapArray[temppos] = heapArray[parent(temppos)];
        temppos = parent(temppos);
    }
    heapArray[temppos] = temp;
}

template<class T>
void MinHeap<T>::swap(int pos_x, int pos_y)     //交换位置x和y的元素
{
    T temp = heapArray[pos_x];
    heapArray[pos_x] = heapArray[pos_y];
    heapArray[pos_y] = temp;
}

template<class T>
T& MinHeap<T>::RemoveMin()                      //从堆顶删除最小值
{
    if (CurrentSize == 0)
    {
        cout<< "Can't Delete" <<endl;
//        exit(0);
    }
    else
    {
        swap(0,--CurrentSize);                  //交换堆顶和最后一个元素
        if(CurrentSize>1)
            SiftDown(0);                        //从堆顶开始筛选
        return heapArray[CurrentSize];
    }
}

template<class T>
bool MinHeap<T>::Remove(int pos, T& node)       // 删除给定下标的元素
{
    if((pos < 0) || (pos >= CurrentSize))
        return false;
    T temp = heapArray[pos];
    heapArray[pos] = heapArray[--CurrentSize];  //指定元素置于最后
    if (pos != 0 && heapArray[parent(pos)] > heapArray[pos])
        SiftUp(pos);                            // 当前元素小于父结点,需要上升调整
    else
        SiftDown(pos);                          // 当前元素大于父结点,向下筛
    node = temp;
    return true;
}

template <class T>
void MinHeap<T>::SiftDown(int left)
{
    int i = left;                       //标识父结点
    int j = leftchild (i);              //标识关键值较小的子结点
    T    temp = heapArray[i];           //保存父结点
    while (j < CurrentSize)             //过筛
    {
        if((j < CurrentSize-1) && (heapArray[j] > heapArray[j + 1]))
            j++;                        //j指向右子结点
        if (temp>heapArray[j])
        {
            heapArray[i] = heapArray[j];
            i = j;
            j = leftchild(j);           //向下继续
        }
        else break;
    }
    heapArray[i] = temp;
}

2. 哈弗曼树类

#include <iostream>
#include "MinHeap.h"
using namespace std;

template <class T> class HuffmanTree;
template <class T>
class HuffmanTreeNode
{
    friend class HuffmanTree<T>;
private:
    T info;
    HuffmanTreeNode<T> *parent;
    HuffmanTreeNode<T> *left;
    HuffmanTreeNode<T> *right;
public:
    HuffmanTreeNode() {};
    HuffmanTreeNode<T> *leftchild()
    {
        return left;
    };
    HuffmanTreeNode<T> *rightchild()
    {
        return right;
    };
    bool operator > (HuffmanTreeNode<T> &HN)
    {
        return info > HN.info;
    }; // 注意要重载运算符
    bool operator < (HuffmanTreeNode<T> &HN)
    {
        return info < HN.info;
    };
    bool operator == (HuffmanTreeNode<T> &HN)
    {
        return info == HN.info;
    };
};

template <class T>
class HuffmanTree
{
private:
    HuffmanTreeNode<T>* root;                       //Huffman树的树根

    //把ht1和ht2为根的Huffman子树合并成一棵以parent为根的二叉树
    void MergeTree ( HuffmanTreeNode<T> &ht1, HuffmanTreeNode<T> &ht2,  HuffmanTreeNode<T>* parent);
    void DeleteTree(HuffmanTreeNode<T>* root);      //删除Huffman树或其子树
public:
    //构造Huffman树,weight是存储权值的数组,n是数组长度
    HuffmanTree(T weight[],int n);
    virtual ~HuffmanTree()
    {
        DeleteTree(root);
    };     //析构函数

    void InOrder(HuffmanTreeNode<T> *root);          //中序周游
    HuffmanTreeNode<T> *GetRoot()
    {
        return root;
    };
};

template<class T>
HuffmanTree<T>::HuffmanTree(T weight[], int n)
{
    MinHeap< HuffmanTreeNode<T> > heap(n);          //定义最小值堆
    HuffmanTreeNode<T> *parent, firstchild, secondchild;
    HuffmanTreeNode<T>* NodeList = new HuffmanTreeNode<T>[n];
    for(int i = 0; i < n; i++)                      //初始化
    {
        NodeList[i].info = weight[i];
        NodeList[i].parent = NodeList[i].left = NodeList[i].right = NULL;
        heap.Insert(NodeList[i]);                   //向堆中添加元素
    }

    for(int i = 0; i < n-1; i++)                    //通过n-1次合并建立Huffman树
    {
        parent = new HuffmanTreeNode<T>;
        firstchild = heap.RemoveMin();              //选择权值最小的结点
        secondchild = heap.RemoveMin();             //选择权值次小的结点
        MergeTree(firstchild, secondchild, parent); //合并权值最小的两棵树
        heap.Insert(*parent);                       //把parent插入到堆中去
        root = parent;                              //建立根结点
    }
    delete []NodeList;
}

template <class T>
void HuffmanTree<T>::DeleteTree(HuffmanTreeNode<T> *root)
{
    if (root)
    {
        DeleteTree(root->left);
        DeleteTree(root->right);
        delete root;
    }
}

template <class T>
void HuffmanTree<T>::InOrder(HuffmanTreeNode<T> *root)    //中序周游
{
    if (root)
    {
        InOrder(root->left);
        cout << root->info << " ";
        InOrder(root->right);
    }
}

template <class T>
void HuffmanTree<T>::MergeTree(HuffmanTreeNode<T> &ht1, HuffmanTreeNode<T> &ht2, HuffmanTreeNode<T> *parent)
{
    HuffmanTreeNode<T> *l = new HuffmanTreeNode<T>();
    HuffmanTreeNode<T> *r = new HuffmanTreeNode<T>();

    *l = ht1; // 不能写为l = &ht1,注意地址引用,开辟的是新空间,或者应用拷贝构造函数,只是有些麻烦
    *r = ht2;

    parent->parent = NULL;
    parent->left = l;
    parent->right = r;
    parent->info = ht1.info + ht2.info;
    ht1.parent = ht2.parent = parent; // 指向父节点
}

int main()
{
    int weight[] = {6,2,3,4};       //权值

    HuffmanTree<int> a(weight,4);   //图5.19 Huffman树
    cout<< "HuffmanTree is constructed. " << endl;

    cout<< "中序周游: " << endl;
    a.InOrder(a.GetRoot());        //中序周游,结果:6 15 4 9 2 5 3
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值