数据结构与算法B代码编写作业,Huffman编码树,解题报告&AC代码

又来写解题报告了,这道题相比于前两道来说都要简单一些。

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树的建立,数据范围小,可以不需要使用堆结构.
    不过鼓励使用第一题实现的堆来寻找最小和次小元素。 


你可能感兴趣的:(数据结构与算法B代码编写作业,Huffman编码树,解题报告&AC代码)