哈夫曼树的建立(二叉链表)C++/DHUOJ/东华大学/数据结构

问题描述 :

内容:请参照二叉树的ADT模板,设计Huffman树的抽象数据类型。(由于该环境目前仅支持单文件的编译,故将所有内容都集中在一个源文件内。在实际的设计中,推荐将抽象类及对应的派生类分别放在单独的头文件中。参考教材、课件,以及网盘中的二叉树ADT原型文件,自行设计Huffman树的ADT。)

 

应用:要求设计一个算法,使用动态存储的方式,实现Huffman树的ADT。

提示:动态存储是指在新添加一个数据元素时,为它申请一个动态变量。删除一个数据元素时,释放该元素的存储空间。huffman树类的行为主要有两个:构造一棵haffuman树和获取叶子结点的Huffman编码。但由于树上的结点都是动态申请的,为此还需要一个析构函数。每个结点要保存的信息有4个:结点的值、结点的权值、左孩子指针、右孩子指针。

注意:为了保证你生成的哈夫曼树和题目的要求一致,需要遵循以下原则:

1、两个结点合并成一棵树时,权重小的结点为新树的左子树,权重大的结点为新树的右子树。

2、如果两个结点权重相等,则本来在左边的结点为新树的左子树。

3、新创建的树始终放在集合(森林)的最右边。


输入范例 :

5
d i a n w
7 5 2 4 9

输出范例 :

(27) (11) (16) i(5) (6) d(7) w(9) a(2) n(4) 
(27) (11) i(5) (6) a(2) n(4) (16) d(7) w(9) 
i(5) (11) a(2) (6) n(4) (27) d(7) (16) w(9) 
i(5) a(2) n(4) (6) (11) d(7) w(9) (16) (27) 

d:10
i:00
a:010
n:011
w:11

template<class T>
struct TreeNode {
    int weight = 0;
    T val;
    int id = 0;
    int flag = 1;
    TreeNode* left;
    TreeNode* right;
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(T x,int w=0) : val(x),weight(w), left(nullptr), right(nullptr) {}
    TreeNode(T x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
};
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
template<class T>
TreeNode<T>* build(T empty) {
    T val;
    cin >> val;
    if (val != empty) {
        TreeNode<T>* node = new TreeNode<T>(val);
        node->left = build<T>(empty);
        node->right = build<T>(empty);
        return node;
    }
    else {
        return NULL;
    }
}
#include <queue>
template<class T>
TreeNode<T>* buildlayer(T empty) {
    string str;
    getline(cin, str);
    stringstream ss(str);
    TreeNode<T>* head = new TreeNode<T>("");
    queue< TreeNode<T>*>q;
    q.push(head);
    while (ss >> str) {
        TreeNode<T>* obj = q.front();
        q.pop();
        if (str != empty) {
            obj->val = str;
            obj->flag = 1;
            obj->left = new TreeNode<T>("");
            obj->left->flag = 0;
            obj->right = new TreeNode<T>("");
            obj->right->flag = 0;
            q.push(obj->left);
            q.push(obj->right);
        }
    }
    while (q.size()) {
        q.front()->flag = 0;
        q.pop();
    }
    return head;
}
template<class T>
void preorder(TreeNode<T>* tree, vector<TreeNode<T>*>& list) {
    if (tree) {
        if (tree->flag)list.push_back(tree);
        preorder(tree->left, list);
        preorder(tree->right, list);
    }
}
template<class T>
void inorder(TreeNode<T>* tree, vector<TreeNode<T>*>& list) {
    if (tree) {

        inorder(tree->left, list);
        if (tree->flag)list.push_back(tree);
        inorder(tree->right, list);
    }
}
template<class T>
TreeNode<T>* seek(TreeNode<T>* t, T target) {
    if (!t)return NULL;
    if (t->val == target)return t;
    auto l = seek(t->left, target), r = seek(t->right, target);
    if (l)return l;
    else return r;
}
template<class T>
TreeNode<T>* seekparent(TreeNode<T>* t, T target) {
    if (!t)return NULL;
    if (t->val == target)return NULL;
    if (t->left && t->left->val == target || t->right && t->right->val == target)
        return t;
    else {
        auto l = seekparent(t->left, target), r = seekparent(t->right, target);
        if (l)return l;
        else return r;
    }
}
template<class T>
void postorder(TreeNode<T>* tree, vector<TreeNode<T>*>& list) {
    if (tree) {
        postorder(tree->left, list);
        postorder(tree->right, list);
        if (tree->flag)list.push_back(tree);
    }
}
template<class T>
void levelOrder(TreeNode<T>* tree, vector<TreeNode<T>*>& list) {
    queue< TreeNode<T>*>q;
    q.push(tree);
    while (q.size()) {
        list.push_back(q.front());
        if (q.front()->left)q.push(q.front()->left);
        if (q.front()->right)q.push(q.front()->right);
        q.pop();
    }
}
template<class T>
void out(TreeNode<T>* head) {
    vector<TreeNode<T>*>pr, in, po, lv;
    levelOrder(head, lv);
    preorder(head, pr);
    inorder(head, in);
    postorder(head, po);
    for (int i = 0; i < lv.size(); ++i) {
        cout << lv[i]->val << "(" << lv[i]->weight << ")" << " ";
    }
    cout << endl;
    for (int i = 0; i < pr.size(); ++i) {
        cout << pr[i]->val<<"("<<pr[i]->weight<<")" << " ";
    }
    cout << endl;
    for (int i = 0; i < in.size(); ++i) {
        cout << in[i]->val << "(" << in[i]->weight << ")" << " ";
    }
    cout << endl;
    for (int i = 0; i < po.size(); ++i) {
        cout << po[i]->val << "(" << po[i]->weight << ")" << " ";
    }
    cout << endl;
}

#include<algorithm>
#include <unordered_map>
struct ch
{
    string val;
    int weight;
    ch(string v = "", int w = 0) {
        val = v;
        weight = w;
    }
};
vector<ch>rawchart;
vector<TreeNode<string>* > chart, pool;
bool cmp(TreeNode<string>* a, TreeNode<string>* b) {
    if(a->weight!=b->weight)
    return a->weight > b->weight;
    return a->val < b->val;
}

TreeNode<string>* combine(TreeNode<string>* a, TreeNode<string>* b) {
    auto res = new TreeNode<string>("", a->weight + b->weight);
    if (a->weight == b->weight)
        cout<<"";
    if (a->weight < b->weight||(a->weight == b->weight&&a->val!="")) {
        res->left = a;
        res->right = b;
    }
    else {
        res->left = b;
        res->right = a;
    }
    //printf("now combine: %s(%d) and %s(%d)\n", a->val.c_str(), a->weight, b->val.c_str(), b->weight);
    return res;
}
unordered_map<string, string>codes;
void dfs(TreeNode<string>* tree, string code) {
    if (tree->val != "")codes[tree->val] = code;
    if (tree->left)dfs(tree->left, code + "0");
    if (tree->right)dfs(tree->right, code + "1");
}
int main() {
    int n;
    cin >> n;

    TreeNode<string>* head = NULL;
    for (int i = 0; i < n; ++i) {
        string c;
        cin >> c;
        ch tmp(c);
        rawchart.push_back(tmp);
    }
    for (int i = 0; i < n; ++i)
        cin >> rawchart[i].weight;
    for (int i = 0; i < n; ++i) {
        chart.push_back(new TreeNode<string>(rawchart[i].val, rawchart[i].weight));
    }

    sort(chart.begin(), chart.end(),cmp);
    pool.push_back(chart.back());
    head = pool[0];
    chart.pop_back();
    while (chart.size()) {
        if (chart.size()==1||pool[0]->weight <= ( chart[chart.size() - 2]->weight)) {
            pool.push_back(chart.back());
            chart.pop_back();
        }
        else {
            auto newnode = combine(chart.back(), chart[chart.size() - 2]);
            chart.pop_back();
            chart.pop_back();
            chart.push_back(newnode);
        }
        sort(chart.begin(), chart.end(), cmp);
        //out(head);
        //cout << endl;

        if (pool.size() == 2) {
            auto newnode = combine(pool[0], pool[1]);
            pool.clear();

            chart.push_back(newnode);
            sort(chart.begin(), chart.end(), cmp);
            pool.push_back(chart.back());
            head = chart.back();
            chart.pop_back();
            //chart.push_back(newnode);
            
        }
        sort(chart.begin(), chart.end(), cmp);
    }
    out(head);
    cout << endl;
    dfs(head,"");
    for (int i = 0; i < rawchart.size(); ++i) {
        cout << rawchart[i].val << ":" << codes[rawchart[i].val] << endl;
    }
    return 0;
}


有疑问欢迎咨询.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值