南邮数据结构、算法实践周基础题3(哈夫曼树及其编码)

来源:互联网 发布:linux 拷贝整个文件夹 编辑:程序博客网 时间:2024/05/19 17:04
是在一位学长的代码上改的,学长勿怪~.~

#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;}



0 0
原创粉丝点击