2024年华为OD机试真题-生成哈夫曼树 C/C++解法

基于哈夫曼树的规则生成哈夫曼树,其中用到了常见的二叉树生成逻辑,最后中序遍历使用递归实现。

cpp 复制代码
#include <iostream>
#include <algorithm>
#include <list>

using namespace std;

// 哈夫曼树节点
struct halfman_tree_node
{
    halfman_tree_node *down_left;
    halfman_tree_node *down_right;
    halfman_tree_node *parent;
    int value;
};

/// @brief 二叉树中序遍历
/// @param tnode
static void halfman_tree_middle_print(halfman_tree_node *tnode)
{
    if (tnode == nullptr)
    {
        return;
    }

    halfman_tree_middle_print(tnode->down_left);  // left
    cout << tnode->value << " ";                  // middle
    halfman_tree_middle_print(tnode->down_right); // right
}

// 生成哈夫曼树
static void HuaWei_OD_test26(void)
{
    int tnode_cnt;
    cin >> tnode_cnt;

    list<int> tnode_weight_list;
    for (int i = 0; i < tnode_cnt; i++)
    {
        int tmp;
        cin >> tmp;
        tnode_weight_list.push_back(tmp);
    }

    list<halfman_tree_node *> halfman_tree_list;

    // 第一次升序
    tnode_weight_list.sort();

    while (tnode_weight_list.size() >= 2)
    {
        // 找到最小的两个元素
        auto small_value1 = tnode_weight_list.begin(); // 最小
        auto small_value2 = tnode_weight_list.begin(); // 倒数第二小
        small_value2++;

        // 将两个元素合并为一个新元素
        int new_node_value = *small_value1 + *small_value2;
        halfman_tree_node *new_tnode = new halfman_tree_node;
        new_tnode->value = new_node_value;
        new_tnode->parent = nullptr;

        // 刚开始没有tnode,构建两个tnode
        if (halfman_tree_list.size() < 2)
        {
            halfman_tree_node *left_tnode = new halfman_tree_node;
            left_tnode->down_left = nullptr;
            left_tnode->down_right = nullptr;
            left_tnode->value = *small_value1;

            halfman_tree_node *right_tnode = new halfman_tree_node;
            right_tnode->down_left = nullptr;
            right_tnode->down_right = nullptr;
            right_tnode->value = *small_value2;

            new_tnode->down_left = left_tnode;
            new_tnode->down_right = right_tnode;

            left_tnode->parent = new_tnode;
            right_tnode->parent = new_tnode;

            halfman_tree_list.push_back(left_tnode);
            halfman_tree_list.push_back(right_tnode);
        }
        else
        {
            // 只需要申请一个新的tnode
            halfman_tree_node *x_tnode = new halfman_tree_node;
            x_tnode->down_left = nullptr;
            x_tnode->down_right = nullptr;

            // 此时halfman_tree_list的最后一个元素是目前的最长节点顶部
            auto current_top = halfman_tree_list.back();

            // 比较current_top节点的权重,和当前最小的权重来选择哪一个元素构建一个新的tnode
            if (current_top->value >= *small_value1)
            {
                x_tnode->value = *small_value1;
                new_tnode->down_left = x_tnode; // 更新顶部
                new_tnode->down_right = current_top;
            }
            else
            {
                x_tnode->value = *small_value2;
                new_tnode->down_left = current_top; // 更新顶部
                new_tnode->down_right = x_tnode;
            }

            x_tnode->parent = new_tnode;
            current_top->parent = new_tnode;

            halfman_tree_list.push_back(x_tnode);
        }

        halfman_tree_list.push_back(new_tnode); // 目前的顶部节点

        tnode_weight_list.pop_front(); // 权重列表去掉最小元素
        tnode_weight_list.pop_front(); // 权重列表去掉第二小元素

        tnode_weight_list.push_front(new_node_value); // 加入新的权重元素
        tnode_weight_list.sort();                     // 重新升序排列
    }

    // 到这里说明tnode_weight_list只有一个权重,也就是根节点的权重
    // 也就意味着halfman_tree_list最后一个元素是根节点

    // 开始进行中序遍历
    auto root = halfman_tree_list.back(); // 根节点

    halfman_tree_middle_print(root);

    // 清理内存
    for (const auto &tnode : halfman_tree_list)
    {
        delete tnode;
    }
}

int main()
{
    HuaWei_OD_test26();
    return 0;
}
相关推荐
R-G-B3 小时前
【25】MFC入门到精通——MFC静态文本框 中字符串 连续输出 不覆盖先前的文本 换行输出
c++·mfc·mfc静态文本框输出字符串·mfc静态文本框连续输出字符串·mfc静态文本框换行输出字符串
FFZero15 小时前
【C++/Lua联合开发】 (二) Lua调用C++函数
c++·junit·lua
CoderCodingNo6 小时前
【GESP】C++四级真题 luogu-B4068 [GESP202412 四级] Recamán
开发语言·c++·算法
一个不知名程序员www6 小时前
算法学习入门---双指针(C++)
c++·算法
Maple_land6 小时前
常见Linux环境变量深度解析
linux·运维·服务器·c++·centos
Larry_Yanan7 小时前
QML学习笔记(四十四)QML与C++交互:对QML对象设置objectName
开发语言·c++·笔记·qt·学习·ui·交互
Want5957 小时前
C/C++大雪纷飞①
c语言·开发语言·c++
Mr_WangAndy7 小时前
C++设计模式_行为型模式_策略模式Strategy
c++·设计模式·策略模式·依赖倒置原则
LoveXming7 小时前
Chapter11—适配器模式
c++·设计模式·适配器模式·开闭原则
Benny_Tang8 小时前
题解:P7989 [USACO21DEC] Bracelet Crossings G
c++·算法