南邮数据结构、算法实践周基础题3(哈夫曼树及其编码)
2016-10-25 16:58
477 查看
是在一位学长的代码上改的,学长勿怪~.~
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
template<class T>
class PrioQueue //优先权队列类
{
public:
PrioQueue(int mSize = 20);
~PrioQueue(){ delete []q; }
bool IsEmpty() const{ return n == 0; }
bool IsFull() const{ return n == maxSize; }
void Append(const T&x);
void Serve(T&x);
private:
void AdjustDown(int r, int j);
void AdjustUp(int j);
T *q;
int n, maxSize;
};
template<class T>
PrioQueue<T>::PrioQueue(int mSize)
{
maxSize = mSize;
n = 0;
q = new T[maxSize];
}
template<class T>
void PrioQueue<T>::AdjustUp(int j)
{
int i = j;
T temp = q[i];
while (i > 0 && temp < q[(i - 1) / 2])
{
q[i] = q[(i - 1) / 2];
i = (i - 1) / 2;
}
q[i] = temp;
}
template<class T>
void PrioQueue<T>::Append(const T&x) //插入新元素
{
if(IsFull())
{
cout << "Overflow" << endl;
return;
}
q[n++] = x;
AdjustUp(n-1);
}
template<class T>
void PrioQueue<T>::Serve(T&x) //删除堆顶元素
{
if(IsEmpty())
{
cout << "Underflow" << endl;
return;
}
x = q[0];
q[0] = q[--n];
AdjustDown(0, n-1);
}
template<class T>
void PrioQueue<T>::AdjustDown(int r,int j) //向上调整
{
int child = 2 * r + 1;
T temp = q[r];
while(child <= j)
{
if((child < j) && (q[child] > q[child+1]))
child++;
if(temp <= q[child])
break;
q[(child - 1) / 2] = q[child];
child = 2 * child + 1;
}
q[(child - 1) / 2] = temp;
}
template<class T>
struct BTNode //结点类
{
BTNode(){lChild = rChild = NULL;}
BTNode(const T&x, const char &y)
{
element = x;
ch = y;
lChild = rChild = parent = NULL;
memset(z, -1, sizeof(z));
}
BTNode(const T&x, const char &y, BTNode<T>*l, BTNode<T>*r)
{
element = x;
ch = y;
lChild = l;
rChild = r;
parent = NULL;
memset(z, -1, sizeof(z));
}
T element;
BTNode<T> *lChild, *rChild, *parent;
char ch;
int val;
int z[100];
};
template<class T> //二叉树类
class BinaryTree
{
public:
BinaryTree(){root = NULL; i = -1;}
~BinaryTree(){}
void MakeTree(const T&x, const char &y, BinaryTree<T>&left, BinaryTree<T>& right);
void Create_code();
void Create_code_out();
BTNode<T>*root;
private:
int i;
void Create_code(BTNode<T>*t);
void Create_code_out(BTNode<T>*t);
// void Make(BTNode<T>*t,char a);
};
template<class T>
void BinaryTree<T>::MakeTree(const T&x, const char &y, BinaryTree<T>&left, BinaryTree<T>& right) //建树
{
if(root || &left == &right)
return;
root = new BTNode<T>(x, y, left.root, right.root);
if(left.root != right.root)
{
left.root -> parent = root;
right.root -> parent = root;
left.root -> val = 0;
right.root -> val = 1;
}
left.root = right.root = NULL;
}
template<class T>
class HfmTree : public BinaryTree<T> //哈夫曼树类
{
public:
operator T() const{ return weight; }
T getW(){ return weight; }
void putW(const T&x){ weight = x; }
void SetNull(){ root = NULL; }
private:
T weight;
};
template<class T>
HfmTree<T> CreateHfmTree(T w[],char q[],int n) //构造哈夫曼树
{
PrioQueue<HfmTree<T> > pq(n);
HfmTree<T> x, y, z, zero;
for(int i = 0; i < n; i++)
{
z.MakeTree(w[i], q[i], x ,y);
z.putW(w[i]);
pq.Append(z);
z.SetNull();
}
for(i = 1; i < n; i++)
{
pq.Serve(x);
pq.Serve(y);
z.MakeTree(x.getW() + y.getW(), 'e', x, y);
z.putW(x.getW() + y.getW());
pq.Append(z);
z.SetNull();
}
pq.Serve(z);
return z;
}
void menu()
{
cout<<"--------------欢迎使用哈夫曼编码和译码系统------------------"<<endl;
cout<<"************** 请选择下列序号进行运算: *****************"<<endl;
cout<<"***************** B--建树 ************************"<<endl;
cout<<"***************** E--生成编码 ************************"<<endl;
cout<<"***************** X--退出 ************************"<<endl<<endl;
cout<<"--------------------- 输入操作项----------------------------"<<endl;
}
HfmTree<int> Ht;
int num;
void Make_Ht()
{
char str[100];
int weight[100];
cout << "请输入字符个数 :";
cin >> num; //建树
cout << "请输入权值 :";
for(int i = 0; i < num; i++)
cin >> weight[i];
cout << "请输入相应字符集 :";
for(i=0;i<num;i++){
cin >> str[i];
}
Ht = CreateHfmTree(weight, str, num);
}
template<class T>
void BinaryTree<T>::Create_code()
{
Create_code(root);
}
template<class T>
void BinaryTree<T>::Create_code(BTNode<T>*t)
{
if(t)
{
if(t -> parent)
{
for(int j = 0; j <= i; j++)
t -> z[j] = t -> parent -> z[j]; //复制双亲的编码域
i++;
t -> z[i] = t-> val; //在编码域中加入自己的编码
}
Create_code(t -> lChild); //递归,先左孩子,再右孩子
Create_code(t -> rChild);
i--;
}
}
template<class T>
void BinaryTree<T>::Create_code_out() //生成编码并输出
{
Create_code_out(root);
}
template<class T>
void BinaryTree<T>::Create_code_out(BTNode<T>*t)
{
if(t)
{
if(t -> lChild == t -> rChild) //叶子结点
{
cout << t -> ch << ":"; //输出叶子结点中的字符
int i = 0;
while(t -> z[i] != -1)
{
cout << t -> z[i]; //输出编码域
i++;
}
cout << endl;
}
Create_code_out(t->lChild);
Create_code_out(t->rChild);
}
}
int main()
{
char choose;
menu();
cin >> choose;
while(choose != 'X')
{
switch(choose)
{
case 'B':
Make_Ht();
Ht.Create_code();
break;
case 'E':
cout << "编码为 :" << endl;
Ht.Create_code_out();
break;
case 'X':
break;
default:
cout << " 输入有误,请重新输入!"<<endl;
break;
}
system("PAUSE");
system("CLS");
menu();
cin >> choose;
}
return 0;
}
相关文章推荐
- 南邮数据结构、算法实践周提高题2(Number Games)
- 夕拾算法进阶篇:26)哈夫曼树及其编码
- *第十五周*数据结构实践项目一【验证哈希表及其算法】
- 南邮数据结构、算法实践周提高题3(图的连通问题和二叉排序树)
- 详解神经网络算法所需最基础数据结构Tensor及其相关操作
- 数据结构&算法实践—【排序|选择排序】堆排序
- 一步一步复习数据结构和算法基础(1)
- RSA算法基础->实践
- 数字电视业务信息及其编码基础知识
- RSA算法基础->实践
- 一步一步复习数据结构和算法基础-栈和队列(2)
- 数据结构&算法实践—【排序|选择排序】选择排序
- RSA算法基础->实践
- RSA算法基础->实践
- 一步一步复习数据结构和算法基础-单链表冒泡排序
- 一步一步复习数据结构和算法基础-循环链表
- 一步一步复习数据结构和算法基础-链表(1)
- 【数据结构与算法基础】栈及其应用后缀、中缀表达式 / Stack and postfix/infix expression
- RSA算法基础->实践
- C#数据结构和算法学习系列五----基础查找算法