哈夫曼树的实现

目录

引言

树节点的创建

HuffmanTree类

类的初始化-构造函数

有参构造 创建HuffmanTree

析构函数

类的方法

1.遍历

2.复制 WPL 释放内存

主程序

1.测试HuffmanTree是否成功创建

​编辑

2.测试拷贝构造函数

3.测试内存释放

引言

本人只是刚入门的萌新,记录一下自己的学习😊

树节点的创建

struct TreeNode
{
    int weight;//权重
    TreeNode* left, * right;//左右孩子
    TreeNode():weight(0),left(NULL),right(NULL){}
    TreeNode(int w) :weight(w), left(NULL), right(NULL) {}
    TreeNode(int w,TreeNode* l,TreeNode* r) :weight(w), left(l), right(r) {}
};

HuffmanTree类

类的成员属性和方法

class HuffmanTree
{
public:
    HuffmanTree();//空构造
    HuffmanTree(const vector<int>& nums);//创建HuffmanTree
    HuffmanTree(TreeNode* root);//拷贝构造
    ~HuffmanTree();//析构函数 释放内存
    void preOrder(TreeNode* root);//前序遍历
    void inOrder(TreeNode* root);//后序遍历
    void postOrder(TreeNode* root);//中序遍历
    void layerOrder();//层次遍历
    int calculateWPL();//计算带权路径和
    void deleteTree(TreeNode* root);//释放内存
    TreeNode* copyTree(TreeNode* root);//树的拷贝
public:
    TreeNode* root;
};
  1. 类的初始化-构造函数

空构造

HuffmanTree::HuffmanTree()
{
    this->root = NULL;
}

有参构造 创建HuffmanTree

class myCmp
{
public:
    bool operator()(TreeNode* left,TreeNode* right)
    {
        return left->weight > right->weight;
    }
};
HuffmanTree::HuffmanTree(const vector<int>& nums)
{
    //利用优先队列的特性 解决每次排序的时间浪费
    priority_queue<TreeNode*, vector<TreeNode*>,myCmp > q;
    for (int i = 0; i < nums.size(); i++)
    {
        TreeNode* node = new TreeNode(nums[i]);
        q.push(node);
    }
    TreeNode* left = NULL, * right = NULL, *root = NULL;
    while (q.size()!=1)
    {
        left = q.top();
        q.pop();
        right = q.top();
        q.pop();
        root = new TreeNode(left->weight + right->weight, left, right);
        q.push(root);
    }
    this->root = root;
}

拷贝构造

HuffmanTree::HuffmanTree(TreeNode* root)
{
    this->root = copyTree(root);
}
  1. 析构函数

HuffmanTree::~HuffmanTree()
{
    if (this->root == NULL) return;
    deleteTree(this->root);
}
  1. 类的方法

1.遍历

前序遍历

void HuffmanTree::preOrder(TreeNode* root)
{
    if (root == NULL) return;
    cout << root->weight << " ";
    preOrder(root->left);
    preOrder(root->right);
}

中序遍历

void HuffmanTree::inOrder(TreeNode* root)
{
    if (root == NULL) return;
    inOrder(root->left);
    cout << root->weight << " ";
    inOrder(root->right);
}

后序遍历

void HuffmanTree::postOrder(TreeNode* root)
{
    if (root == NULL) return;
    postOrder(root->left);
    postOrder(root->right);
    cout << root->weight << " ";
}

层次遍历

void HuffmanTree::layerOrder()
{
    if (this->root == NULL) return;
    queue<TreeNode*> q;
    q.push(root);
    while (!q.empty())
    {
        int len = q.size();
        TreeNode* tmp;
        for (int i = 0; i < len; i++)
        {
            tmp = q.front();
            q.pop();
            cout << tmp->weight << " ";
            if (tmp->left != NULL) q.push(tmp->left);
            if (tmp->right != NULL) q.push(tmp->right);
        }
        cout << endl;
    }
}

2.复制 WPL 释放内存

  1. 树的复制

TreeNode* HuffmanTree::copyTree(TreeNode* root)
{
    if (root == NULL) return NULL;
    TreeNode* left = copyTree(root->left);
    TreeNode* right = copyTree(root->right);
    root = new TreeNode(root->weight, left, right);
    return root;
}
  1. 计算带权路径总和

广度优先搜索 与层次遍历的思想一致

int HuffmanTree::calculateWPL()
{
    if (this->root == NULL) return 0;
    int ans = 0,layer=0;
    queue<TreeNode*> q;
    q.push(root);
    while (!q.empty())
    {
        int len = q.size();
        TreeNode* tmp;
        for (int i = 0; i < len; i++)
        {
            tmp = q.front();
            q.pop();
            if (tmp->left != NULL) q.push(tmp->left);
            if (tmp->right != NULL) q.push(tmp->right);
            if (tmp->left == NULL && tmp->right == NULL) ans += (tmp->weight * layer);
        }
        layer++;
    }
    return ans;
}
  1. 释放内存

void HuffmanTree::deleteTree(TreeNode* root)
{
    if (root == NULL) return;
    deleteTree(root->left);
    deleteTree(root->right);
    delete root;
    this->root = NULL;//将成员root置空 防止野指针
}

主程序

#include<iostream>
using namespace std;
#include<vector>
#include<queue>
struct TreeNode
{
    int weight;
    TreeNode* left, * right;
    TreeNode():weight(0),left(NULL),right(NULL){}
    TreeNode(int w) :weight(w), left(NULL), right(NULL) {}
    TreeNode(int w,TreeNode* l,TreeNode* r) :weight(w), left(l), right(r) {}
};
class HuffmanTree
{
public:
    HuffmanTree();//空构造
    HuffmanTree(const vector<int>& nums);//创建HuffmanTree
    HuffmanTree(TreeNode* root);//拷贝构造
    ~HuffmanTree();//析构函数 释放内存
    void preOrder(TreeNode* root);//前序遍历
    void inOrder(TreeNode* root);//后序遍历
    void postOrder(TreeNode* root);//中序遍历
    void layerOrder();//层次遍历
    int calculateWPL();//计算带权路径和
    void deleteTree(TreeNode* root);//释放内存
    TreeNode* copyTree(TreeNode* root);//树的拷贝
public:
    TreeNode* root;
};
class myCmp
{
public:
    bool operator()(TreeNode* left,TreeNode* right)
    {
        return left->weight > right->weight;
    }
};
void test01(const vector<int>& nums)//测试HuffmanTree是否成功创建
{
    HuffmanTree t(nums);
    cout << "前序遍历: "; t.preOrder(t.root); cout << endl;
    cout << "中序遍历: "; t.inOrder(t.root);cout << endl;
    cout << "后序遍历: "; t.postOrder(t.root);cout << endl;
    cout << "层次遍历: " << endl; t.layerOrder(); 
    cout << "带权路径总和(WPL): " << t.calculateWPL() << endl;
}
void test02(const vector<int>& nums)//验证拷贝构造函数
{
    HuffmanTree t1(nums);
    cout << "层次遍历: " << endl; t1.layerOrder();
    HuffmanTree t2(t1.root);
    cout << "层次遍历: " << endl; t1.layerOrder();
}
void test03(const vector<int>& nums)//测试内存释放
{
    HuffmanTree t(nums);
    t.deleteTree(t.root);//提前释放内存,查看是否与析构时冲突
    cout << "层次遍历: " << endl; t.layerOrder();
}
int main()
{
    vector<int> nums{ 10,20,50,100 };
    //测试HuffmanTree是否成功创建
    //test01(nums);
    //验证拷贝构造函数
    //test02(nums);
    //测试内存释放
    test03(nums);
    return 0;
}

HuffmanTree::HuffmanTree()
{
    this->root = NULL;
}

HuffmanTree::HuffmanTree(const vector<int>& nums)
{
    //利用优先队列的特性 解决每次排序的时间浪费
    priority_queue<TreeNode*, vector<TreeNode*>,myCmp > q;
    for (int i = 0; i < nums.size(); i++)
    {
        TreeNode* node = new TreeNode(nums[i]);
        q.push(node);
    }
    TreeNode* left = NULL, * right = NULL, *root = NULL;
    while (q.size()!=1)
    {
        left = q.top();
        q.pop();
        right = q.top();
        q.pop();
        root = new TreeNode(left->weight + right->weight, left, right);
        q.push(root);
    }
    this->root = root;
}

HuffmanTree::HuffmanTree(TreeNode* root)
{
    this->root = copyTree(root);
}

HuffmanTree::~HuffmanTree()
{
    if (this->root == NULL) return;
    deleteTree(this->root);
}

void HuffmanTree::preOrder(TreeNode* root)
{
    if (root == NULL) return;
    cout << root->weight << " ";
    preOrder(root->left);
    preOrder(root->right);
}

void HuffmanTree::inOrder(TreeNode* root)
{
    if (root == NULL) return;
    inOrder(root->left);
    cout << root->weight << " ";
    inOrder(root->right);
}

void HuffmanTree::postOrder(TreeNode* root)
{
    if (root == NULL) return;
    postOrder(root->left);
    postOrder(root->right);
    cout << root->weight << " ";
}

void HuffmanTree::layerOrder()
{
    if (this->root == NULL) return;
    queue<TreeNode*> q;
    q.push(root);
    while (!q.empty())
    {
        int len = q.size();
        TreeNode* tmp;
        for (int i = 0; i < len; i++)
        {
            tmp = q.front();
            q.pop();
            cout << tmp->weight << " ";
            if (tmp->left != NULL) q.push(tmp->left);
            if (tmp->right != NULL) q.push(tmp->right);
        }
        cout << endl;
    }
}

int HuffmanTree::calculateWPL()
{
    if (this->root == NULL) return 0;
    int ans = 0,layer=0;
    queue<TreeNode*> q;
    q.push(root);
    while (!q.empty())
    {
        int len = q.size();
        TreeNode* tmp;
        for (int i = 0; i < len; i++)
        {
            tmp = q.front();
            q.pop();
            if (tmp->left != NULL) q.push(tmp->left);
            if (tmp->right != NULL) q.push(tmp->right);
            if (tmp->left == NULL && tmp->right == NULL) ans += (tmp->weight * layer);
        }
        layer++;
    }
    return ans;
}

void HuffmanTree::deleteTree(TreeNode* root)
{
    if (root == NULL) return;
    deleteTree(root->left);
    deleteTree(root->right);
    delete root;
    this->root = NULL;//将成员root置空 防止野指针
}

TreeNode* HuffmanTree::copyTree(TreeNode* root)
{
    if (root == NULL) return NULL;
    TreeNode* left = copyTree(root->left);
    TreeNode* right = copyTree(root->right);
    root = new TreeNode(root->weight, left, right);
    return root;
}

1.测试HuffmanTree是否成功创建

void test01(const vector<int>& nums)//测试HuffmanTree是否成功创建
{
    HuffmanTree t(nums);
    cout << "前序遍历: "; t.preOrder(t.root); cout << endl;
    cout << "中序遍历: "; t.inOrder(t.root);cout << endl;
    cout << "后序遍历: "; t.postOrder(t.root);cout << endl;
    cout << "层次遍历: " << endl; t.layerOrder(); 
    cout << "带权路径总和(WPL): " << t.calculateWPL() << endl;
}

测试结果正确 实现树的创建

2.测试拷贝构造函数

void test02(const vector<int>& nums)//验证拷贝构造函数
{
    HuffmanTree t1(nums);
    cout << "层次遍历: " << endl; t1.layerOrder();
    HuffmanTree t2(t1.root);
    cout << "层次遍历: " << endl; t1.layerOrder();
}

两棵树的节点一致,并实现深拷贝(t1和t2析构时不发生冲突)

 

3.测试内存释放

void test03(const vector<int>& nums)//测试内存释放
{
    HuffmanTree t(nums);
    t.deleteTree(t.root);//提前释放内存,查看是否与析构时冲突
    cout << "层次遍历: " << endl; t.layerOrder();
}

树被清空且不与析构函数发生冲突

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值