您的位置:首页 > 理论基础 > 数据结构算法

南邮数据结构、算法实践周基础题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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  哈夫曼树