浅谈【数据结构】树与二叉树之哈夫曼树

目录

1、哈夫曼树

1.1哈夫曼编码

1.2哈夫曼树

1.3构建一棵哈夫曼树


谢谢帅气美丽且优秀的你看完我的文章还要点赞、收藏加关注

没错,说的就是你,不用再怀疑!!!

希望我的文章内容能对你有帮助,一起努力吧!!!


1、哈夫曼树

1.1哈夫曼编码

在电报通信过程中,电文是以二进制0/1序列传送的,每一个字符对应了一个二进制的编码。

为了缩短按电文长度,采用不等长的编码方式,把使用频率较高的字符采用短编码。使用频率低的字符 采用长的编码。

1.2哈夫曼树

哈夫曼树:又称为最优二叉树

它是由n个带权的叶子结点构成的所有二叉树中,带权路径长度 WPL 最小的二叉树

一棵树的带权路径长度:树中所有叶子结点的带权路径长度之和。

结点的带权路径长度:从根结点开始到该结点的路径的长度与该结点上的权值的乘积。

1.3构建一棵哈夫曼树

假设N个权值,分别为W1,W2,W3....Wn的叶子结点,构建这一棵哈夫曼树的规则:

  • 第一步:
    • 构建森林
      • 把每一个叶子结点作为一棵独立的树看待(只有根结点的树),这样就拥有了n棵树的以 一个森林
      • 把森林存放到一个优先队列(不是队列)中,方便取出最小的结点。
  • 第二步:
    • 从优先队列中取出权值最小的两棵树(结点),再创建一棵新结点,将新结点设为两个最小结 点的父结点。父结点的权值就是两个结点的权值之和。
  • 第三步:
    • 将创建好的新结点加入到优先队列中。
  • 第四步:
    • 重复第二步和第三步直到优先队列中只剩一个结点,该节点就是哈夫曼树的根结点。

***示例代码***

#include <iostream>
#include <queue>


template <typename __queue_node_type__>
class priorityQueue
{
private:
    typedef struct node
    {
        __queue_node_type__ data;
        struct node *next;
    }Node;

    Node *first;
    Node *final;
    int   count;
public:
    priorityQueue()
        :first(nullptr)
        ,final(nullptr)
        ,count(0)
    {}
    ~priorityQueue()
    {}
    void push(__queue_node_type__ data_t)
    {
        // 新结点
        Node *new_ptr = new Node;
        new_ptr->data = data_t;
        new_ptr->next = nullptr;

        // 是否为链表中第一个结点
        if(count == 0)
        {
            first = new_ptr;
            final = new_ptr;
            // 更新个数
            count++;
            return;
        }
        else
        {
            if(first->data > data_t)
            {
                new_ptr->next = first;
                first = new_ptr;
                // 更新个数
                count++;
                return;
            }
            // 查找插入位置
            Node *node_ptr = first;
            while(node_ptr->next)
            {
                if(node_ptr->data > data_t)
                {
                    new_ptr->next = node_ptr->next;
                    node_ptr->next = new_ptr;
                    count++;
                    return;
                }
                node_ptr = node_ptr->next;
            }
        }

        final->next = new_ptr;
        final = new_ptr;
        count++;
        return;
    }
    __queue_node_type__ pop()
    {
        if(count == 0)
            throw int(-1);
        __queue_node_type__ data_t = first->data;

        Node *node_ptr = first;
        first = first->next;

        node_ptr->next = nullptr;
        delete node_ptr;
        count--;
        return data_t;
    }
    int length() const
    {
        return count;
    }
};



template <typename __tree_node_type__>
class HafuManTree
{
private:
    typedef struct node
    {
        __tree_node_type__ weight;
        struct node *lchild;
        struct node *rchild;
    } Node;

    Node *root;
public:
    HafuManTree(std::initializer_list<__tree_node_type__> list)
     : root(nullptr)
    {
        // 构建森林
        // 创建一个优先队列
        priorityQueue<Node*> queue;

        // 第一步:把所有的结点存入优先队列
        for(auto var : list)
        {
            Node *node_ptr = new Node;
            node_ptr->weight = var;
            node_ptr->lchild = nullptr;
            node_ptr->rchild = nullptr;
            queue.push(node_ptr);
        }

        // 第四步:重复第二步和第三步
        while(queue.length()!=1)
        {
            // 第二步:取出权值最小的两棵树(结点),再创建一棵新结点
            Node* data1 = queue.pop();
            Node* data2 = queue.pop();
            
            // 第三步创建新结点作为两个结点的父节点
            Node* newfather = new Node;
            newfather->weight = data1->weight + data2->weight;

            newfather->lchild = data1;
            newfather->rchild = data2;

            // 把新结点存入优先队列
            queue.push(newfather);
        }

        // 最后一个元素是哈夫曼树的根结点
        root = queue.pop();
    }


    ~HafuManTree(){}

    void levelprint()
    {
        std::queue<Node*> queque;

        queque.push(root);

        while(queque.size())
        {
            Node *node_ptr = queque.front();
            queque.pop();

            if(node_ptr->lchild)
                queque.push(node_ptr->lchild);
            if(node_ptr->rchild)
                queque.push(node_ptr->rchild);
            std::cout << node_ptr->weight << std::endl;
        }
    }
};


int main()
{
    HafuManTree<int> tree({1,2,3,4,5,6,7,8,9});

    tree.levelprint();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值