南郵データ構造実験2(2)ハフマン符号化とコンパイルシステム


ハフマン符号化とコンパイルシステム
1.設計されたシステムは、次のメニュー項目を繰り返し表示します.
B:ツリーを作る:文字セットと各文字の頻度を読み込んで、ハフマンツリーを作る.
T-遍歴:先序と中序は二叉木を遍歴する.
E-生成符号化:作成されたハフマンツリーに基づいて、各文字のハフマン符号化を生成する.
C-符号化:文字セット文字からなる任意の文字列を入力、生成したハフマン符号化により符号化し、符号化結果を表示し、入力文字列とその符号化結果をそれぞれディスクファイルtextfileに保存する.txtとcodefile.txtで.
D-デコード:codefileを読み込む.txtは、作成するハフマンツリーを用いて復号し、復号結果をディスクファイルresultに格納する.txt.
P-印刷:ファイルtextfileが画面に表示する.txt,codefile.txt,result.txt.
X-脱退.
 
このプログラムはVC++6.0上でコンパイルして実行して間違いがありません
 
#include <iostream>
#include <fstream>
#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 PreOrder(void (*Visit)(T&x));
	void InOrder(void (*Visit)(T&x));
	void Create_code();
	void Create_code_out();
	void Code();
	void Compile();
	void Print();
	BTNode<T>*root;
private:
	int i;
	void PreOrder(void (*Visit)(T&x), BTNode<T>*t);
	void InOrder(void (*Visit)(T&x), BTNode<T>*t);
	void Create_code(BTNode<T>*t);
	void Create_code_out(BTNode<T>*t);
	void Code(BTNode<T>*t);
	void Make(BTNode<T>*t,char a);
	void Compile(BTNode<T>*t);
};

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>                                //Visit  
void Visit(T&x) 
{
	cout << x << " ";
}

template<class T>
void BinaryTree<T>::PreOrder(void (*Visit)(T&x))        //    
{
	cout << "     : ";
	PreOrder(Visit, root);
	cout << endl;
}

template<class T>
void BinaryTree<T>::PreOrder(void (*Visit)(T&x), BTNode<T>*t)
{
	if(t)
	{
		Visit(t -> element);
		PreOrder(Visit, t -> lChild);
		PreOrder(Visit, t -> rChild);
	}
}

template<class T>
void BinaryTree<T>::InOrder(void (*Visit)(T&x))         //    
{
	cout << "     : ";
	InOrder(Visit, root);
	cout << endl;
}

template<class T>
void BinaryTree<T>::InOrder(void (*Visit)(T&x), BTNode<T>*t)
{
	if(t)
	{
		InOrder(Visit, t -> lChild);
		Visit(t -> element);
		InOrder(Visit, t -> rChild);
	}
}

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<<"*****************      T--        ************************"<<endl;
	cout<<"*****************      E--      ************************"<<endl;
	cout<<"*****************      C--        ************************"<<endl;
	cout<<"*****************      D--        ************************"<<endl;
	cout<<"*****************      P--        ************************"<<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 << "         :";
        cin >> str;
	Ht = CreateHfmTree(weight, str, num);
}

void Traversal_Ht()                                            
{ 
	Ht.PreOrder(Visit);
	Ht.InOrder(Visit);
} 

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

template<class T>
void BinaryTree<T>::Code()
{
	Code(root);
}

template<class T>
void BinaryTree<T>::Code(BTNode<T>*t)             //  
{
	ofstream outf("textfile.txt");
	if(!outf)
	{
		cout << "Cannot open the file
"; return; } ofstream outs("codefile.txt",ios::trunc); if(!outs) { cout << "Cannot open the file
"; return; } outs.close(); char str2[100]; cout << " : "; cin >> str2; outf << str2; outf.close(); int l = strlen(str2); cout << " :" << endl; for(int i = 0; i < l; i++) Make(root, str2[i]); cout << endl; } template<class T> void BinaryTree<T>::Make(BTNode<T> *t,char a) { int i = 0; if(t) { if(t -> ch == a) // { ofstream outs("codefile.txt",ios::app); while(t -> z[i] != -1) { cout << t -> z[i]; // outs << t -> z[i]; // i++; } outs.close(); return; } Make(t -> lChild, a); Make(t -> rChild, a); } } template<class T> void BinaryTree<T>::Compile() // { Compile(root); } template<class T> void BinaryTree<T>::Compile(BTNode<T> *t) { ifstream inf("codefile.txt"); if(!inf) { cout << "Cannot open the file
"; return; } ofstream outs("result.txt",ios::trunc); if(!outs) { cout << "Cannot open the file
"; return; } outs.close(); char *re; char tmp; int n = 0; while(inf.get(tmp) != '\0') { n++; // } inf.close(); re = new char[n+1]; int n2 = 0; ifstream in("codefile.txt"); if(!in) { cout<<"Cannot open the file
"; return; } while(in.get(tmp) != '\0') { re[n2] = tmp; // n2++; } BTNode<T> *c; cout << " :"; int n3 = 0; while(n3 < n) { while(t) { c = t; if(re[n3] == '0') // 0 1 0 1 t = t -> lChild; else t = t -> rChild; n3++; } ofstream outs("result.txt",ios::app); if(!outs) { cout << "Cannot open the file
"; return; } cout << c -> ch; // outs << c -> ch; // outs.close(); t = root; n3--; } cout << endl; } void Print() { char str; ifstream a("textfile.txt"); ifstream b("codefile.txt"); ifstream c("result.txt"); if(!a) { cout << "Cannot open the file
"; return; } if(!b) { cout << "Cannot open the file
"; return; } if(!c) { cout << "Cannot open the file
"; return; } cout << "textfile.txt :"; while(a.get(str) != '\0') cout << str; cout << endl; cout << "codefile.txt :"; while(b.get(str) != '\0') cout << str; cout << endl; cout << "result.txt :"; while(c.get(str) != '\0') cout << str; cout << endl; a.close(); b.close(); c.close(); } int main() { char choose; menu(); cin >> choose; while(choose != 'X') { switch(choose) { case 'B': Make_Ht(); Ht.Create_code(); break; case 'T': Traversal_Ht(); break; case 'E': cout << " :" << endl; Ht.Create_code_out(); break; case 'C': Ht.Code(); break; case 'D': Ht.Compile(); break; case 'P': Print(); break; case 'X': break; default: cout << " , !"<<endl; break; } system("PAUSE"); system("CLS"); menu(); cin >> choose; } return 0; }