南邮 OJ 1022 哈夫曼编码与译码

哈夫曼编码与译码

时间限制(普通/Java) :  1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 491            测试通过 : 185 

比赛描述

已知电文包括的字符集为{ACIMNPTU},输入对应权值,对字符集合进行哈夫曼编码,完成电文的哈夫曼编码与译码工作。

输入

共三行:

第一行为对应字符集{ACIMNPTU}的权值

第二行为一段字符串表示的电文(长度不超过1000);

第三行为一段电文的哈夫曼编码。

输出

共十行:

前八行为各字符的编码;

第九行是与第二行输入对应的哈夫曼编码;

第十行是与第三行输入对应的电文。

样例输入

1 2 3 4 5 6 7 8
NUPTICPCACM
1111011111100

样例输出

A: 11110
C: 11111
I: 1110
M: 100
N: 101
P: 110
T: 00
U: 01
1010111000111011111110111111111011111100
ACM

提示

2012.4.11 更新

题目来源

NUPT ACM



#include <iostream>
#include <cassert>
#include <string>
#define MAX(a,b) (a>b?a:b)
using namespace std;

template<typename Type>
class QueueNode{
public:
	Type data;
	QueueNode *next;
};

template<typename Type>
class Queue{
public:
	QueueNode<Type> *Head;			//指向第一个元素,方便出队
	QueueNode<Type> *Tail;			//指向最后一个元素,方便插入

	void PushBack(const Type&);
	Type PopFront(void);
};

/*
*函数功能:队尾加入新元素
*入口参数:const Type& data:将要插入的元素
*出口参数:无
*作者:陈汝军
*时间:2014-8-19 20:17:13
*/
template<typename Type>
void Queue<Type>::PushBack(const Type& data){
	if(Head == NULL){
		Head = new QueueNode<Type>();
		Head->data = data;
		Tail = Head;
	}else{
		Tail->next = new QueueNode<Type>();
		Tail->next->data = data;
		Tail = Tail->next;	
	}
}
/*
*函数功能:队首弹出元素
*入口参数:无
*出口参数:Type PopFront:弹出的元素
*作者:陈汝军
*时间:2014-8-19 20:18:08
*/ 
template<typename Type>
Type Queue<Type>::PopFront(void){
	QueueNode<Type> *TempHead = Head;
	Type TempData = Head->data;
	assert(Head!=NULL);
	Head = Head->next;
	delete TempHead;
	return TempData;
}


template<typename Type>
class BTNode{
public:
	Type data;
	BTNode *lChild;
	BTNode *rChild;
	BTNode *parent;

	void PreOrder(void);
	void InOrder(void);
	void PostOrder(void);
	static void PreOrderInput(BTNode<Type>* &Head);		//静态成员函数,调用与具体的类无关
	int  Height(void);
	int  NodeNum(void);
	int  LeafNum(void);
	void TransLevel(void);
	void Exchange(void);
};


/*
*函数功能:先序遍历二叉树。
*入口参数:this.
*出口参数:无
*作者:陈汝军
*时间:2014-8-18 22:01:59
*/

template<typename Type>
void BTNode<Type>::PreOrder(){
	if(this == NULL)
		return;
	cout<<" "<<this->data;
	this->lChild->PreOrder();
	this->rChild->PreOrder();
}
/*
*函数功能:中序遍历二叉树。
*入口参数:this.
*出口参数:无
*作者:陈汝军
*时间:2014-8-18 22:03:36
*/
template<typename Type>
void BTNode<Type>::InOrder(){
	if(this == NULL)
		return;
	this->lChild->InOrder();
	cout<<" "<<this->data;
	this->rChild->InOrder();	
}
/*
*函数功能:后序遍历二叉树。
*入口参数:this.
*出口参数:无
*作者:陈汝军
*时间:2014-8-18 22:04:09
*/
template<typename Type>
void BTNode<Type>::PostOrder(){
	if(this == NULL)
		return;
	this->lChild->PostOrder();
	this->rChild->PostOrder();
	cout<<" "<<this->data;
}
/*
*函数功能:先序输入二叉树,用#代表空树或空子树。
*入口参数:BTNode* &Head:树的节点指针的引用
*出口参数:无
*作者:陈汝军
*时间:2014-8-18 22:01:59
*/
template<typename Type>
void BTNode<Type>::PreOrderInput(BTNode* &Head){
	Type data;
	cin>>data;
	if(data == '#'){
		Head = NULL;	
	}else{
		Head = new BTNode<Type>();
		Head->data = data;
		BTNode<char>::PreOrderInput(Head->lChild);
		BTNode<char>::PreOrderInput(Head->rChild);	
	}
}
/*
*函数功能:输出二叉树的高度
*入口参数:this:本节点指针
*出口参数:Height:高度
*作者:陈汝军
*时间:2014-8-19 10:21:03
*/
template<typename Type>
int BTNode<Type>::Height(void){
	if(this == NULL){
		return 0;
	}else{
		return MAX(this->lChild->Height(),this->rChild->Height())+1;
	}
}
/*
*函数功能:求二叉树的总结点数
*入口参数:this:本节点指针
*出口参数:NodeNum:以本节点为树根的总节点数
*作者:陈汝军
*时间:2014-8-19 10:24:16
*/
template<typename Type>
int BTNode<Type>::NodeNum(void){
	if(this == NULL){
		return 0;
	}else{
		return this->lChild->NodeNum()+this->rChild->NodeNum()+1;
	}	
}
/*
*函数功能:求二叉树的叶节点数
*入口参数:this:本节点指针
*出口参数:LeafNum:以本节点为树根的叶节点数
*作者:陈汝军
*时间:2014-8-19 10:29:36
*/
template<typename Type>
int BTNode<Type>::LeafNum(void){
	if(this==NULL){
		return 0;
	}else if(this->lChild==NULL && this->rChild==NULL){
		return 1;
	}else{
		return this->lChild->LeafNum()+this->rChild->LeafNum();
	}	
}
/*
*函数功能:层次遍历二叉树
*入口参数:无
*出口参数:无
*作者:陈汝军
*时间:2014-8-19 20:48:29
*/
template<typename Type>
void BTNode<Type>::TransLevel(void){
	Queue<BTNode<Type>*> *que = new Queue<BTNode<Type>*>();
	if(this == NULL)
		return;
	que->PushBack(this);
	while(que->Head!=NULL){					//输出整个队列,输出过程中队列在增长
		if(que->Head->data->lChild!=NULL){
			que->PushBack(que->Head->data->lChild);
		}
		if(que->Head->data->rChild!=NULL){
			que->PushBack(que->Head->data->rChild);
		}
		cout<<" "<<que->PopFront()->data;
	}
}
/*
*函数功能:二叉树上所有左右子树互换
*入口参数:无
*出口参数:无
*作者:陈汝军
*时间:2014-8-20 19:20:40
*/
template<typename Type>
void BTNode<Type>::Exchange(void){
	BTNode<Type> *Temp;
	if(this == NULL){
		return;
	}
	if(this->lChild!=NULL || this->rChild!=NULL){
		Temp = this->lChild;
		this->lChild = this->rChild;
		this->rChild = Temp;
	}
	this->lChild->Exchange();
	this->rChild->Exchange();
}
///////////////////////////////////////////////////////////////////////上面是通用模板
class HufCode{
public:
	char ch;
	int weight;
};

typedef BTNode<HufCode> HufTree;
class HufLink{
public:
	HufTree *hTree;
	HufLink *next;
	void InsertAndSort(char newchar,int newweight);
	void InsertAndSort(HufLink *newLink);
	void outputList(void);
};
ostream& operator<<(ostream &out,const HufCode &hCode)           //我是输出操作符的重载
{
	out<<hCode.weight<<" "<<hCode.ch<<endl;
 return out;
}
/*
*函数功能:往HufLink中插入一个新元素。
*入口参数:char newchar:新元素的ch值
           int newweight:新元素的weight值
*出口参数:无
*作者:陈汝军
*时间:2014-8-21 09:06:14
*/
void HufLink::InsertAndSort(char newchar,int newweight){
	HufLink *p=this;
	HufLink *q=new HufLink();
	q->hTree = new HufTree();
	q->hTree->data.ch = newchar;
	q->hTree->data.weight = newweight;
	if(p->next == NULL){		//链表中一个元素也没有
		p->next = q;
		return;
	}
	while(p->next!=NULL && p->next->hTree->data.weight<newweight){
		p = p->next;
	}
	q->next = p->next;
	p->next = q;
}
/*
*函数功能:往HufLink中插入一个已经存在的新元素。
*入口参数:HufLink *newLink:指向新元素的指针
*出口参数:无
*作者:陈汝军
*时间:2014-8-21 09:07:00
*/
void HufLink::InsertAndSort(HufLink *newLink){
	HufLink *p=this;
	if(p->next == NULL){		//链表中一个元素也没有
		p->next = newLink;
		return;
	}
	while(p->next!=NULL && p->next->hTree->data.weight<newLink->hTree->data.weight){
		p = p->next;
	}
	newLink->next = p->next;
	p->next = newLink;
}
/*
*函数功能:从头到尾输出Huffman链表
*入口参数:无
*出口参数:无
*作者:陈汝军
*时间:2014-8-20 20:01:45
*/
void HufLink::outputList(void){
	HufLink *p=this->next;			//头指针没有元素
	while(p!=NULL){
		cout<<p->hTree->data.ch<<":"<<p->hTree->data.weight<<endl;
		p = p->next;
	}
}

/*HufLink里面存放*HufCode是建立不好树的,HufLink中应该存放HufTree*/
HufTree* makeHufTree(HufLink* hLink){
	HufLink *p,*q,*newNode;
	if(hLink==NULL || hLink->next==NULL){	//HufLink头指针不存放元素
		return NULL;
	}
	while(hLink->next->next!=NULL){
		newNode = new HufLink();
		newNode->hTree = new HufTree();
		p = hLink->next;
		q = hLink->next->next;
		newNode->hTree->data.weight = p->hTree->data.weight+q->hTree->data.weight;
		if(p->hTree->data.weight<q->hTree->data.weight){
			newNode->hTree->lChild = p->hTree;		//左小右大
			newNode->hTree->rChild = q->hTree;
			p->hTree->parent = newNode->hTree;
			q->hTree->parent = newNode->hTree;
		}else{
			newNode->hTree->lChild = q->hTree;		//左小右大
			newNode->hTree->rChild = p->hTree;
			p->hTree->parent = newNode->hTree;
			q->hTree->parent = newNode->hTree;
		}
		hLink = hLink->next->next;
		hLink->InsertAndSort(newNode);
	}
	return hLink->next->hTree;
}
class CodeLink{						//头指针不放元素
public:
	bool codebit;
	CodeLink *next;
	void addBit(bool bit);
	void reverse(void);
};
void CodeLink::addBit(bool bit){
	CodeLink *p=this,*q=new CodeLink();
	q->codebit = bit;
	if(p->next ==NULL){
		p->next = q;
		return;
	}
	while(p->next!=NULL){
		p = p->next;
	} 
	p->next = q;
}
void CodeLink::reverse(void){
	CodeLink *p=this->next,*q=NULL;
	if(p == NULL){
		return;
	}
	while(p->next!=NULL){
		q = p->next;
		p->next = q->next;
		q->next = this->next;
		this->next = q;

	}
}
	
CodeLink* cLink[256]={NULL};	//所有ASCII码到Huffman码转换
void cLinks(HufTree* hTree){
	HufTree *p=hTree;
	if(hTree == NULL)
		return;
	if(p->lChild==NULL && p->rChild==NULL){	//是叶节点
		cLink[hTree->data.ch] = new CodeLink();
		while(p->parent!=NULL){
			if(p->parent->lChild == p){
				cLink[hTree->data.ch]->addBit(0);	//做孩子0
			}else{
				cLink[hTree->data.ch]->addBit(1);	//右孩子1
			}
			p = p->parent;
		}
		cLink[hTree->data.ch]->reverse();
	}
	cLinks(hTree->lChild);
	cLinks(hTree->rChild);
}
void printHufCode(char ch){
	CodeLink *p=cLink[ch]->next;
	while(p!=NULL){
		cout<<p->codebit;
		p = p->next;
	}
}
int main(void){
	int weight[256]={0},i=0;
	string str,num;
	HufLink *hLink = new HufLink();
	cin>>weight['A']>>weight['C']>>weight['I']>>weight['M']>>weight['N']>>weight['P']>>weight['T']>>weight['U'];
	cin>>str>>num;
	hLink->InsertAndSort('A',weight['A']);
	hLink->InsertAndSort('C',weight['C']);
	hLink->InsertAndSort('I',weight['I']);
	hLink->InsertAndSort('M',weight['M']);
	hLink->InsertAndSort('N',weight['N']);
	hLink->InsertAndSort('P',weight['P']);
	hLink->InsertAndSort('T',weight['T']);
	hLink->InsertAndSort('U',weight['U']);
//	hLink->outputList();
	HufTree *hTree = makeHufTree(hLink),*p=NULL;
//	hTree->PreOrder();
	cLinks(hTree);
	cout<<"A: ";printHufCode('A');cout<<endl;
	cout<<"C: ";printHufCode('C');cout<<endl;
	cout<<"I: ";printHufCode('I');cout<<endl;
	cout<<"M: ";printHufCode('M');cout<<endl;
	cout<<"N: ";printHufCode('N');cout<<endl;
	cout<<"P: ";printHufCode('P');cout<<endl;
	cout<<"T: ";printHufCode('T');cout<<endl;
	cout<<"U: ";printHufCode('U');cout<<endl;
	while(str[i]!='\0'){
		printHufCode(str[i]);
		++i;
	}
	cout<<endl;
	p = hTree;
	i = 0;
	while(num[i]!='\0'){		
		if(num[i] == '0'){
			p = p->lChild;
		}else{
			p = p->rChild;
		}
		if(p->lChild==NULL && p->rChild==NULL){				//叶节点
			cout<<p->data.ch;
			p = hTree;
		}
		++i;
	}
	cout<<endl;
	return 0;
}



你可能感兴趣的:(ACM,哈夫曼,南邮OJ,编码与译码)