又来写解题报告了,这道题相比于前两道来说都要简单一些。
Huffman树的生成办法很简单:从指定节点堆中选出最小的两个节点作为左右子树,它们的和为父节点,将父节点加入节点堆,从节点堆中删除子树的节点。
程序的实现就是模拟上面的过程生成这棵二叉树。
其中要注意的一点就是如何选出最小的两个节点:我这里使用了C++中STL的Priority_Queue,这是一个现成的顺序队列,好用、省时。
就说这么多啦,也没啥说的了,AC代码奉上。
/*
ID: Moien_Podiene
LANG: C++
*/
#include <iostream>
#include <cstdlib>
#include <queue>
using namespace std;
class BinTreeNode;
class BinTreeNode
{
public:
BinTreeNode(); //缺省构造函数
BinTreeNode(int); //由当前节点的变量值(参数)创建节点
BinTreeNode(int, BinTreeNode *, BinTreeNode *); 由当前节点的变量值(参数1)、左右子树指针(参数2,3)创建节点
BinTreeNode *GetLeftChild(); //返回当前节点的左孩子指针
BinTreeNode *GetRightChild(); //返回当前节点的右孩子指针
BinTreeNode *SetLeftChild(BinTreeNode *); //由参数中的节点设置当前节点的左孩子,返回左孩子指针
BinTreeNode *SetRightChild(BinTreeNode *); //由参数中的节点设置当前节点的右孩子,返回右孩子指针
int GetData(); //获取节点值
int SetData(int); //设置节点值,返回设置的值
bool operator<(BinTreeNode);
bool operator==(BinTreeNode);
private:
int data; //当前节点的值
BinTreeNode *leftChild;
BinTreeNode *rightChild;
};
int BinTreeNodeCompare(const void *, const void *); //比较节点数据大小
int WeighCalculate(BinTreeNode *, int); //计算外部路径长度和,参数2为当前深度
bool operator<(BinTreeNode, BinTreeNode);
const int MAX_NUM = 256; //最大节点数
int main()
{
int caseNum; //测试数据组数
int originNum, nodeNum; //每组测试数据节点数,当前二叉树总结点数
int buff; //节点数据缓存
BinTreeNode *binBuff; //节点缓存
BinTreeNode binTree[MAX_NUM];
cin >> caseNum;
for(int i = 0; i < caseNum; i++)
{
BinTreeNode leftTemp; //左子树缓存
BinTreeNode rightTemp; //右子树缓存
priority_queue<BinTreeNode> binTreeQueue;
cin >> originNum;
nodeNum = 0;
for(int j = 0; j < originNum; j++)
{
cin >> buff;
binBuff = new BinTreeNode(buff);
binTreeQueue.push(*binBuff);
delete binBuff;
}
for(int j = 0; j < originNum - 1; j++)
{
leftTemp = binTreeQueue.top();
binTreeQueue.pop();
rightTemp = binTreeQueue.top();
binTreeQueue.pop();
binTree[nodeNum++] = leftTemp;
binTree[nodeNum++] = rightTemp; //队列顶的前两个元素即为最小的两个元素
binBuff = new BinTreeNode(leftTemp.GetData() + rightTemp.GetData(),
&(binTree[nodeNum - 2]), &(binTree[nodeNum - 1]));
binTreeQueue.push(*binBuff);
if(j == originNum - 2)
binTree[nodeNum++] = binTreeQueue.top();
delete binBuff;
}
qsort(binTree, nodeNum, sizeof(BinTreeNode), BinTreeNodeCompare);
BinTreeNode *root = &binTree[nodeNum - 1];
cout << WeighCalculate(root, 0) << endl;
}
return 0;
}
BinTreeNode::BinTreeNode()
{
data = -1;
leftChild = rightChild = NULL;
}
BinTreeNode::BinTreeNode(int val)
{
data = val;
leftChild = rightChild = NULL;
}
BinTreeNode::BinTreeNode(int val, BinTreeNode *left, BinTreeNode *right)
{
data = val;
leftChild = left;
rightChild = right;
}
BinTreeNode *BinTreeNode::GetLeftChild()
{
return leftChild;
}
BinTreeNode *BinTreeNode::GetRightChild()
{
return rightChild;
}
BinTreeNode *BinTreeNode::SetLeftChild(BinTreeNode *val)
{
leftChild = val;
return leftChild;
}
BinTreeNode *BinTreeNode::SetRightChild(BinTreeNode *val)
{
rightChild = val;
return rightChild;
}
int BinTreeNode::GetData()
{
return data;
}
int BinTreeNode::SetData(int val)
{
data = val;
return data;
}
bool BinTreeNode::operator<(BinTreeNode x)
{
return data > x.GetData(); //与小于判断相反,达成队列由小到大排列的目的
}
bool BinTreeNode::operator==(BinTreeNode x)
{
if(data != x.GetData())
return false;
else if(leftChild != x.GetLeftChild())
return false;
else if(rightChild != x.GetRightChild())
return false;
return true;
}
int BinTreeNodeCompare(const void *x, const void *y)
{
return ((BinTreeNode *)x) -> GetData() - ((BinTreeNode *)y) -> GetData();
}
int WeighCalculate(BinTreeNode *root, int level)
{
if(root == NULL)
return 0;
if(root -> GetLeftChild() == NULL && root -> GetRightChild() == NULL) //递归出口,叶节点
return root -> GetData() * level;
return WeighCalculate(root -> GetLeftChild(), level + 1) +
WeighCalculate(root -> GetRightChild(), level + 1); //递归求左右子树深度和
}
bool operator<(BinTreeNode x, BinTreeNode y)
{
return x.GetData() > y.GetData();
}
坚挺的惯例君在这里:原题
Huffman编码树
查看
提交
统计
提问
总时间限制:
1000ms
内存限制:
65535kB
描述
构造一个具有n个外部节点的扩充二叉树,每个外部节点Ki有一个Wi对应,作为该外部节点的权。使得这个扩充二叉树的叶节点带权外部路径长度总和最小:
Min( W1 * L1 + W2 * L2 + W3 * L3 + … + Wn * Ln)
Wi:每个节点的权值。
Li:根节点到第i个外部叶子节点的距离。
编程计算最小外部路径长度总和。
输入
第一行输入一个整数t,代表测试数据的组数。
对于每组测试数据,第一行输入一个整数n,外部节点的个数。第二行输入n个整数,代表各个外部节点的权值。
2<=N<=100
输出
输出最小外部路径长度总和。
样例输入
2
3
1 2 3
4
1 1 3 5
样例输出
9
17
提示
仅考查huffman树的建立,数据范围小,可以不需要使用堆结构.
不过鼓励使用第一题实现的堆来寻找最小和次小元素。