数据结构课程的二叉树和哈弗曼实验
BTNode.h
template<class T>
struct BTNode
{
BTNode(){lChild=rChild=NULL;}
BTNode(const T& x)
{
element=x;
lChild=rChild=NULL;
}
BTNode(const T& x,BTNode<T>* l,BTNode<T>* r)
{
element=x;
lChild=l;
rChild=r;
}
T element;
BTNode<T>* lChild,*rChild;
};
///
//BinaryTree.h
#include<iostream.h>
#include "Node.h"
#include<queue>
template<class T>
//BinaryTree's public and private functions
class BinaryTree
{
public:
BinaryTree(){ root=NULL; }
//~BinaryTree( );
bool IsEmpty()const{return root==NULL;}
void Clear();
bool Root(T& x)const;
T GetRoot(T& x);
void MakeTree(const T& x,BinaryTree<T>& left,BinaryTree<T>& right);
void BreakTree(T& x,BinaryTree<T>& left,BinaryTree<T>& right);
void PreOrder();
void InOrder();
void PostOrder();
void LevelOrder();
int Size();
int Node1Sum();
int Height();
void ChangeChild();
BTNode<T>* Copy(BTNode<T>* t);
protected:
BTNode<T> *root;
private:
void Clear(BTNode<T>* r);
void PreOrder(BTNode<T>*t);
void InOrder(BTNode<T>*t);
void PostOrder(BTNode<T>*t);
void LevelOrder(BTNode<T>*t);
int Size(BTNode<T> * t);
int Height(BTNode<T>* t);
int Node1Sum(BTNode<T>* t,int sum);
void ChangeChild(BTNode<T>* t);
};
//we can get the root code's element
template<class T>
T BinaryTree<T>::GetRoot(T& x)
{
x=root->element;
return x;
}
//this interface function can change the BinaryTree's left and right children through next private function
template<class T>
void BinaryTree<T>::ChangeChild()
{
ChangeChild(root);
}
template<class T>
void BinaryTree<T>::ChangeChild(BTNode<T> *t)
{
BTNode<T> *temp;
if(t)
{
temp=t->lChild;
t->lChild=t->rChild;
t->rChild=temp;
}
if(t->lChild)
ChangeChild(t->lChild);
if(t->rChild)
ChangeChild(t->rChild);
}
//this interface can get the BinaryTree's height by using the next private function
template<class T>
int BinaryTree<T>::Height()
{
return Height(root);
}
template<class T>
int BinaryTree<T>::Height(BTNode<T> *t)
{
if(t)
{
int h1=Height(t->lChild)+1;
int h2=Height(t->rChild)+1;
return h1>h2?h1:h2;
}
return 0;
}
//this interface can disguish whether have root node
template<class T>
bool BinaryTree<T>::Root(T& x)const
{
if(root)
{
x=root->element;
return true;
}
else return false;
}
//we can make a Binarytree by using this function
template<class T>
void BinaryTree<T>::MakeTree(const T& x, BinaryTree<T>& left,BinaryTree<T>& right)
{
if(root||&left==&right) return;
root=new BTNode<T>(x,left.root,right.root);
left.root=right.root=NULL;
}
template<class T>
void BinaryTree<T>::BreakTree(T& x,BinaryTree<T>& left,BinaryTree<T>& right)
{
if(!root||&left==&right||left.root||right.root)
return;
x=root->element;
left.root=root->lChild;
right.root=root->rChild;
delete root;
root=NULL;
}
template<class T>
void BinaryTree<T>::PreOrder()
{
PreOrder(root);
}
template<class T>
void BinaryTree<T>::PreOrder(BTNode<T>* t)
{
if(t)
{
cout<<t->element;
PreOrder(t->lChild);
PreOrder(t->rChild);
}
}
template<class T>
void BinaryTree<T>::InOrder()
{
InOrder(root);
}
template<class T>
void BinaryTree<T>::InOrder(BTNode<T>* t)
{
if(t)
{
InOrder(t->lChild);
cout<<t->element;
InOrder(t->rChild);
}
}
template<class T>
void BinaryTree<T>::PostOrder()
{
PostOrder(root);
}
template<class T>
void BinaryTree<T>::PostOrder(BTNode<T>* t)
{
if(t){
PostOrder(t->lChild);
PostOrder(t->rChild);
cout<<t->element<<" ";
}
}
template<class T>
void BinaryTree<T>::LevelOrder()
{
LevelOrder(root);
}
template<class T>
void BinaryTree<T>::LevelOrder(BTNode<T> *t)
{
queue<BTNode<T>* > q;
if(t)
q.push(t);
cout<<"LevelOrder:";
while(q.size()>0)
{
BTNode<T>* u=q.front();
q.pop();
cout<<u->element<<" ";
if(u->lChild)
q.push(u->lChild);
if(u->rChild)
q.push(u->rChild);
}
}
//get the BinaryTree's nodes' number
template<class T>
int BinaryTree<T>::Size()
{
return Size(root);
}
template<class T>
int BinaryTree<T>::Size(BTNode<T> * t)
{
if(!t)
return 0;
else
return Size(t->lChild)+Size(t->rChild)+1;
}
//copy a BinaryTree
template<class T>
BTNode<T>* BinaryTree<T>::Copy(BTNode<T>* t)
{
if(!t)
return NULL;
BTNode<T>* q=new BTNode<T>(t->element);
q->lChild=Copy(t->lChild);
q->rChild=Copy(t->rChild);
return q;
}
//destory a tree
template<class T>
void BinaryTree<T>::Clear()
{
Clear(root);
}
template<class T>
void BinaryTree<T>::Clear(BTNode<T>* r)
{
if(r)
{
Clear(r->lChild);
Clear(r->rChild);
Clear(r);
}
}
//get the number of who has one child node
template<class T>
int BinaryTree<T>::Node1Sum()
{
return Node1Sum(root,0);
}
template<class T>
int BinaryTree<T>::Node1Sum(BTNode<T> *t,int sum)
{
if(t)
{
if((t->lChild&&t->rChild==NULL)&&(t->rChild&&t->lChild==NULL))
{
sum++;
}
Node1Sum(t->lChild,sum);
Node1Sum(t->rChild,sum);
}
return sum;
}
#ifndef S_HFMTREE
#define S_HFMTREE
//
//HfmTree.h
#include "BTree.h"
#include "prioQueue.h"
#include<fstream.h>
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;
}
void CreateHfmTree(T w[],int n);
bool MakeCode(char ch[],T w[],BTNode<T>* p[],char* code[],int n);
bool CalCoding(char ch[], T w[], BTNode<T>* p[], char* code[], int n);
BTNode<T>* TranCoding(char *code)const;
T AntiCoding();
private:
T weight;
void MakeCode(BTNode<T> *r,int n,char ch[],T w[],BTNode<T>* p[],char **code,bool b[],int top,char stack[]);
void CalCoding(BTNode<T>* r, char ch[], T w[], BTNode<T>* p[], char* code[], bool b[], char stack[], int top, int n);
BTNode<T>* TranCoding(BTNode<T>* r, char *code) const;
T AntiCoding(char *code[]);
};
template<class T>
T HfmTree<T>::AntiCoding()
{
AntiCoding();
}
template<class T>
T HfmTree<T>::AntiCoding(char *code[])
{
char *stack=char ch[10];
}
//创造一颗hfmtree
template<class T>
void HfmTree<T>::CreateHfmTree(T w[],int n)
{
PrioQueue <HfmTree<T> > pq(n);
HfmTree<T> x,y,z,zero;
for(int i=0;i<n;i++)
{
z.MakeTree(w[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(),x,y);
z.putW(x.getW()+y.getW());
pq.Append(z);
z.SetNull();
}
pq.Serve(z);
root=z.root;
weight=z.weight;
}
//翻译编码
template<class T>
BTNode<T>* HfmTree<T>::TranCoding(char *code)const
{
if(NULL == root || '\0' == *code)
return NULL;
if(NULL == root->lChild && NULL == root->rChild)
return root;
if('0' == *code && NULL != root->lChild)
return TranCoding(root->lChild,code+1);
if('1' == *code && NULL != root->lChild)
return TranCoding(root->rChild,code+1);
return NULL;
}
template <class T>
BTNode<T>* HfmTree<T>::TranCoding(BTNode<T>* r, char *code) const
{
if(NULL == r->lChild && NULL == r->rChild)
return r;
if('0' == *code && NULL != r->lChild)
return TranCoding(r->lChild,code+1);
if('1' == *code && NULL != r->rChild)
return TranCoding(r->rChild,code+1);
return NULL;
}
//生成编码
template <class T>
bool HfmTree<T>::CalCoding(char ch[], T w[], BTNode<T>* p[], char* code[], int n)
{
bool* b = new bool[n];
char* stack = new char[n];
for(int i=0; i<n; i++)
{
b[i] = true;
}
if(IsEmpty())
return false;
if(NULL == root->lChild && NULL == root->rChild)
return false;
CalCoding(root,ch,w,p,code,b,stack,-1,n);
delete[] b;
delete[] stack;
return true;
}
template <class T>
void HfmTree<T>::CalCoding(BTNode<T>* r, char ch[], T w[], BTNode<T>* p[], char* code[], bool b[], char stack[], int top, int n)
{
if(NULL==r->lChild && NULL==r->rChild) // leaf node
{
int i;
for(i=0; i<n; i++)
if(r->element==w[i] && b[i])
break;
b[i] = false;
p[i] = r;
cout<<ch[i]<<" : ";
code[i] = new char[top+1+1];
for(int j=0; j<top+1; j++)
{
cout<<stack[j];
code[i][j] = stack[j];
}
cout<<endl;
code[i][j] = '\0';
}
else // unleaf node
{
if(NULL != r->lChild)
{
stack[++top] = '0';
CalCoding(r->lChild, ch, w, p, code, b, stack, top, n);
--top;
}
if(NULL != r->rChild)
{
stack[++top] = '1';
CalCoding(r->rChild, ch, w, p, code, b, stack, top, n);
--top;
}
}
}
#endif
//PrioQueue.h
#include "resultcode.h"
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);
void Output();
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>::Append(const T &x)
{
if(IsFull()) throw Overflow;
q[n++]=x;
AdjustUp(n-1);
}
template<class T>
void PrioQueue<T>::Serve(T &x)
{
if(IsEmpty()) throw Underflow;
x=q[0];
q[0]=q[--n];
AdjustDown(0,n-1);
}
template<class T>
void PrioQueue<T>::AdjustDown(int i,int j)
{
int child=2*i+1;
T temp=q[i];
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;
temp.SetNull();
}
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;
temp.SetNull();
}
template<class T>
void PrioQueue<T>::Output()
{
for(int i=0;i<n;i++)
{
cout<<q[i]<<" ";
}
}
// main.cpp
//---------------------------------------------------------
//----------------------------------------------------------
// Include file
//----------------------------------------------------------
#include<fstream>
#include<iostream.h>
#include "HfmTree.h"
using namespace std;
//----------------------------------------------------------
// External functions
//----------------------------------------------------------
void HCode(const char c[], char *code[], const int n);
void TranCoding(const HfmTree<int> &ht, char c[], BTNode<int> *np[], char* code[]);
void ShowFile();
void HIntext();
//----------------------------------------------------------
// Helper functions
//----------------------------------------------------------
/* visit function for tracing the tree */
/* Menu for main */
void MMenu()
{
cout<<"\n\t主菜单:\n";
cout<<"\t1\t二叉树的基本操作\n";
cout<<"\t2\t哈夫曼系统\n";
cout<<"\t0\t退出\n";
cout<<"\n\t请输入选择:";
}
//----------------------------------------------------------
// Binary tree contral
//----------------------------------------------------------
/* Menu for BTreeCtrl */
void BTMenu()
{
cout<<"\n\t二叉树菜单\n";
cout<<"\t1\t二叉树的高度\n";
cout<<"\t2\t二叉树的节点数\n";
cout<<"\t3\t二叉树度为一的节点数\n";
cout<<"\t4\t二叉树根节点的值\n";
cout<<"\t5\t二叉树是否为空\n";
cout<<"\t6\t交换二叉树的左右子树\n";
cout<<"\t7\t先序遍历\n";
cout<<"\t8\t中序遍历\n";
cout<<"\t9\t后序遍历\n";
cout<<"\ta\t层次遍历\n";
cout<<"\n\tb\t创建二叉树\n";
cout<<"\tc\t删除二叉树\n";
cout<<"\t0\t退出\n";
cout<<"\n\t请输入选择:";
}
/* Create a binary tree
* n is indentation
*/
void CreateBTree(BinaryTree<char> &bt, int n)
{
char temp;
BinaryTree<char> bt1,bt2;
// indentation
for(int i=0; i<n; i++)
cout<<" ";
// element
cout<<"L"<<n+1<<": 节点数据的值(如果此节点为NULL,请输入#):";
cin>>temp;
if('#' == temp)
return ;
// left child
for(i=0; i<n; i++)
cout<<" ";
cout<<"左子树:\n";
CreateBTree(bt1,n+1);
// right child
for(i=0; i<n; i++)
cout<<" ";
cout<<"右子树:\n";
CreateBTree(bt2,n+1);
// make tree
bt.MakeTree(temp,bt1,bt2);
}
/* Contral for Binary tree test */
void BTreeCtrl()
{
char ch;
BinaryTree<char> bt;
char temp;
do
{
BTMenu();
cin>>ch;
switch(ch)
{
case '1': cout<<"二叉树的高度为:"<<bt.Height()<<endl; break;
case '2': cout<<"二叉树的节点数为:"<<bt.Size()<<endl; break;
case '3': cout<<"二叉树度为一的节点数为:"<<bt.Node1Sum()<<endl; break;
case '4':
if(bt.Root(temp))
cout<<"二叉树根节点为:"<<temp<<endl;
else
cout<<"二叉树为空!\n";
break;
case '5':
if(bt.IsEmpty())
cout<<"二叉树为空\n";
else
cout<<"二叉树非空\n";
break;
case '6':
bt.ChangeChild();
cout<<"二叉树左右子树已交换。\n"; break;
case '7': cout<<"先序遍历:\n"; bt.PreOrder(); break;
case '8': cout<<"中序遍历:\n"; bt.InOrder(); break;
case '9': cout<<"后序遍历:\n"; bt.PostOrder(); break;
case 'a': cout<<"层次遍历:\n"; bt.LevelOrder(); break;
case 'b': cout<<"请按提示输入数据。\n"; CreateBTree(bt,0); cout<<"建树成功!\n"; break;
case 'c': bt.Clear(); cout<<"二叉树已删除!\n"; break;
default:
ch = '0';
}
}while('0' != ch);
}
//----------------------------------------------------------
// HfmTree contral
//----------------------------------------------------------
/* Menu for HTreeCtrl */
void HTMenu()
{
cout<<"\n\t哈夫曼树菜单\n";
cout<<"\t1\t创建哈夫曼树\n";
cout<<"\t2\t先序和中序遍历哈夫曼树\n";
cout<<"\t3\t生成编码\n";
cout<<"\t4\t编码\n";
cout<<"\t5\t译码\n";
cout<<"\t6\t打印\n";
cout<<"\t0\t退出\n";
cout<<"\n\t请输入选择:";
}
/* Clear the array */
template <class T>
inline void ClearArray(T a[],int n)
{
if(NULL != a)
for(int i=0; i<n; i++)
a[i] = NULL;
}
/* delete the array's elements */
template <class T>
inline void DeleteArray(T a[],int n)
{
if(NULL != a && NULL != a[0])
for(int i=0; i<n; i++)
delete[] (a[i]);
}
/* Create tree */
void CreateHTree(int &num, int* &wp, char* &cp, HfmTree<int> &ht)
{
cout<<"请输入要编码的字符数:";
cin>>num;
if(num <= 0)
{
cout<<"输入错误!\n";
return ;
}
if(NULL != wp)
delete[] wp;
if(NULL != cp)
delete[] cp;
wp = new int[num];
cp = new char[num];
cout<<"请按提示输入数据\n";
cout<<"请输入字符"<<endl;
for(int i=0; i<num; i++)
{
cin>>cp[i];
}
cout<<"请输入每个字符的权值"<<endl;
for(i=0;i<num;i++)
{
cin>>wp[i];
}
ht.CreateHfmTree(wp, num);
}
/* Contral for HfmTree */
void HTreeCtrl()
{
char ch;
int num = 0;
int *wp = NULL;
char *cp = NULL;
char **code = NULL;
BTNode<int> **np = NULL;
HfmTree<int> ht;
do
{
HTMenu();
cin>>ch;
switch(ch)
{
case '1':
CreateHTree(num,wp,cp,ht);
np = new BTNode<int>* [num];
code = new char* [num];
ClearArray(np,num);
ClearArray(code,num);
cout<<"建树完成!\n";
break;
case '2':
cout<<"先序遍历:\n";
ht.PreOrder();
cout<<"中序遍历:\n";
ht.InOrder();
// getch();
break;
case '3':
DeleteArray(np,num);
DeleteArray(code,num);
if(ht.IsEmpty())
{
cout<<"请先创建哈夫曼树树!\n";
break;
}
ht.CalCoding(cp, wp, np, code, num);
cout<<"编码生成完毕\n";
break;
case '4':
if(0 == num || NULL == code && NULL == code[0])
{
cout<<"请先创建哈夫曼树,并生成编码!\n";
break;
}
HIntext();
HCode(cp,code,num);
cout<<"编码完毕\n";
break;
case '5':
TranCoding(ht, cp, np, code);
cout<<"译码完毕\n";
break;
case '6':
ShowFile();
break;
default:
ch = '0';
}
}while('0' != ch);
}
//----------------------------------------------------------
// Main function
//----------------------------------------------------------
int main()
{
char ch;
cout<<"\n实验二\n";
cout<<"\nB11040805 陈佳佳"<<endl;
do
{
MMenu();
cin>>ch;
switch(ch)
{
case '1':// BianryTree
BTreeCtrl();
break;
case '2':// HfmTree
HTreeCtrl();
break;
default:
ch = '0';
}
}while('0' != ch);
return 0;
}
void HIntext()
{
char ch;
FILE *fp;
fp=fopen("D:\\textfile.txt","w");
if(!fp)
{
printf("文件不能打开");
}
// cout<<"输入要编码的字符"<<endl;
printf("Enter a text end with '#'\n");
ch=getchar();
while(ch!='#')
{
fputc(ch,fp);
ch=getchar();
}
fclose(fp);
}
void HCode(const char cp[],char* code[] ,int n)
{
char ch;
FILE *fp,*fpc;
fp=fopen("D:\\textfile.txt","r");
if(!fp)
{
printf("文件不能打开");
}
// char chc;
// FILE *fpc;
fpc=fopen("D:\\codefile.txt","w");
if(!fpc)
{
printf("文件不能打开");
}
while((ch=fgetc(fp))!=EOF)
{
for(int i=0;i<n;i++)
{
if(ch==cp[i])
{
fputs(code[i],fpc);
}
}
}
fclose(fp);
fclose(fpc);
}
void TranCoding(const HfmTree<int> &ht, char c[], BTNode<int> *np[], char* code[])
{
char ch;
FILE *fpr,*fpc;
fpr=fopen("D:\\resultfile.txt","w");
fpc=fopen("D:\\codefile.txt","r");
if(!fpr)
{
printf("resultfile文件不能打开");
}
if(!fpc)
{
printf("codefile文件不能打开");
}
BTNode<int> *btnp;
char *pcode = new char[100];
char *p = pcode;
while((ch=fgetc(fpc))!=EOF)
{
*p=ch;
p++;
}
*p = '\0';
p = pcode;
while('\0' != *p)
{
btnp = ht.TranCoding(p);
// find the number of the charector
int i = -1;
while( btnp != np[++i] )
NULL;
//fout<<c[i];
fputc(c[i],fpr);
int j = -1;
while('\0' != code[i][++j])
NULL;
p += j;
}
delete[] pcode;
fclose(fpr);
fclose(fpc);
}
void ShowFile()
{
char ch;
FILE *fpr,*fpc,*fp;
fp=fopen("D:\\textfile.txt","r");
fpr=fopen("D:\\resultfile.txt","r");
fpc=fopen("D:\\codefile.txt","r");
if(!fpr)
{
printf("resultfile文件不能打开");
}
if(!fpc)
{
printf("codefile文件不能打开");
}
if(!fp)
{
cout<<"textfile文件不能打开"<<endl;
}
cout<<"textfile.txt"<<endl;
while((ch=fgetc(fp))!=EOF)
{
putchar(ch);
}
cout<<endl;
cout<<"codefile.txt"<<endl;
while((ch=fgetc(fpc))!=EOF)
{
putchar(ch);
}
cout<<endl;
cout<<"resultfile.txt"<<endl;
while((ch=fgetc(fpr))!=EOF)
{
putchar(ch);
}
cout<<endl;
fclose(fp);
fclose(fpr);
fclose(fpc);
}