Symbol code file

Filename: symbol.cpp
Project Name: Huffman Encoding Trees
Language: C++
Description:

Code:

//========================================================
// CHARACTER METHODS
//========================================================

Symbol::Symbol() {
	Parent = NULL;
	LeftChild = NULL;
	RightChild = NULL;
	Probability=0;
	Character='\0';
	Mark = false;
	CodeBit[0] = '\0';
	Depth = 1;	
}

//==========================================					
Symbol::Symbol(char InputChar, float InputProb) {
	Parent = NULL;
	LeftChild = NULL;
	RightChild = NULL;
	Mark = false;
	CodeBit[0] = '\0';
	Depth = 1;
	
	Character = InputChar;
	Probability = InputProb;
	
}

//==========================================					
Symbol::~Symbol() {;}

//========================================================
// TREE METHODS
//========================================================

Tree::Tree() {
	Root = NULL;
	Count=0;
	PtrCurrent=Root;
	Depth=0;
	BranchCounter=0;
	}

//==========================================					
Tree::~Tree() {	//Delete all Character objects before
					//Destruction
	}

//========================================================
//INSERTSYMBOL IS USED BY THE LIST TREE TO CONSTRUCT
//A LINKED LIST OF SYMBOLS. FOR THIS PURPOSE, IT USES
//THE LEFTCHILD POINTERS TO POINT TO THE NEXT ENTRY AND
//PARENT POINTERS TO POINT TO THE LAST ENTRY
void Tree::insertSymbol(char MyCharacter, float MyProb){
	Symbol *Ptr = new Symbol(MyCharacter,MyProb);
	assert (Ptr !=NULL);
	Ptr->LeftChild = Root;
	Root->Parent = Ptr;
	Root = Ptr;
	Count++;
	
	//Watch for special case of an empty tree
	if (Root == NULL) {
		Root = PtrCurrent = Ptr;
		return;
		}
	
	return;
	}

//==========================================					
//THIS OVERLOADED METHOD IS USED TO INSERT A SYMBOL
//OBJECT INTO THE HUFFMAN TREE
void Tree::insertSymbol(Symbol *Symbol1, Symbol *Symbol2) {
	Symbol *Nanny = new Symbol();
	Nanny->LeftChild = Symbol1;
	Nanny->RightChild = Symbol2;
	Symbol1->Parent = Symbol2->Parent = Nanny;
	Nanny->Probability = Symbol1->Probability + Symbol2->Probability;
	BranchCounter++;
	
	if (BranchCounter==1)
		Root=Nanny;
		
	if (BranchCounter>=2) {
		Symbol *NewRoot=new Symbol();
		NewRoot->LeftChild=Root;
		NewRoot->RightChild=Nanny;
		Nanny->Parent = Root->Parent = NewRoot;
		NewRoot->Probability = Root->Probability + Nanny->Probability;
		Root=NewRoot;
		}
	}

//==========================================					
//THIS OVERLOADED METHOD IS USED TO INSERT A SYMBOL
//OBJECT INTO THE HUFFMAN TREE
void Tree::insertSymbol(Symbol *Symbol1) {
	Symbol *NewRoot = new Symbol;
	NewRoot->LeftChild = Root;
	NewRoot->RightChild = Symbol1;
	Root->Parent = Symbol1->Parent = NewRoot;
	NewRoot->Probability = Symbol1->Probability + Root->Probability;
	BranchCounter++;
	Root=NewRoot;
	}
	
	
//==========================================					
int Tree::showLength(void){
	return Count;
	}

//==========================================					
void Tree::displayTree() {
	for (Symbol *Ptr=Root; Ptr; Ptr=Ptr->LeftChild)
		cout << Ptr->Character << " " << Ptr->Probability << " ";
	cout << endl;
	}
	
//==========================================					
//FINDLOW FINDS THE LOWEST UNMARKED SYMBOL IN THE LIST.
//IF ALL SYMBOLS ARE USED UP (I.E. MARKED), IT RETURNS
//-1. OTHERWISE IT RETURNS 0
int Tree::findLow() {
	Symbol *Ptr = Root;
	bool FoundFlag = false;
	float LowValue = 1;
	
	while (Ptr != NULL) {
		if ((Ptr->Probability<=LowValue) && (Ptr->Mark==false)) {
			FoundFlag = true;
			PtrCurrent=Ptr;
			LowValue = Ptr->Probability;
			}
		Ptr=Ptr->LeftChild;
		}
	
	if (FoundFlag == true)
		return 0;
	else
		return -1;
	}

//==========================================					
int Tree::markSymbol(){
	if (PtrCurrent == NULL)
		return -1;
	else {
		PtrCurrent->Mark = true;
		return 0;
		}
	}

//==========================================					
Symbol* Tree::removeSymbol(){
	Symbol *Tmp;
		
	if (Root == NULL)		//Is the list empty?
		return 0;
		
	if ((PtrCurrent->Mark != true) || (PtrCurrent == NULL))
		return 0;

	//EXTRICATE SYMBOL FROM LIST TREE
	Tmp = PtrCurrent;
	if (PtrCurrent != Root)
		PtrCurrent->LeftChild->Parent = PtrCurrent->Parent;
	else {
		PtrCurrent->LeftChild->Parent=NULL;
		Root=PtrCurrent->LeftChild;
		}	
	PtrCurrent->Parent->LeftChild = PtrCurrent->LeftChild;
	PtrCurrent->Parent=PtrCurrent->LeftChild = NULL;
	PtrCurrent = NULL;
											
	return Tmp;
	}
//==========================================					
void Tree::moveSymbols(Tree *HuffmanTree){
	Symbol *Symbol1=NULL, *Symbol2=NULL;
	int Length=this->showLength();
		
	while (Length > 1) {
		if (findLow()) {
			Symbol1=NULL;
			cerr << "Error: Lowest value not found" << endl;
			}
		else {	
			markSymbol();
			Symbol1=removeSymbol();
			Length--;
			}

		if (findLow()){
			Symbol2=NULL;
			cerr << "Error: Lowest value not found" << endl;
			}
		else{
			markSymbol();
			Symbol2=removeSymbol();
			Length--;
			}
		HuffmanTree->insertSymbol(Symbol1,Symbol2);
		}
		
	if (Length == 1) {
		if (!findLow())
			cerr << "Error: Last element not found!" << endl;
		markSymbol();
		Symbol1=removeSymbol();
		Length--;		
		HuffmanTree->insertSymbol(Symbol1);
		}
			
	return;
	}

//==========================================					
void Tree::printTree(){
	Symbol *Current=Root;
	if (Root != NULL) {
		//Print Header
		cout << "Char Probability   Code              Location   Neighbours" \
		<< endl;		
		printTree(Root->LeftChild);
		printTree(Root->RightChild);

		cout << hex;
		cout <<setiosflags(ios::fixed | ios::showpoint | ios::internal);
		cout << setiosflags(ios::unitbuf | ios::right);
		cout << "\""<< setw(1) << Current->Character<<"\"";
		if (Current->Character=='\0') cout << " ";
		cout << setiosflags(ios::left);
		cout << setw(12) << setprecision(7)	<< Current->Probability << "    ";
		cout << setw(17) << setfill(' ') << Current->CodeBit;
		cout << " " << hex << Current;
		cout << " " << hex << Current->Parent << " " << Current->LeftChild;
		cout << " " << Current->RightChild << dec << endl;
		}
	return;
	}
									
//==========================================					
void Tree::printTree(Symbol *Current){
	if (Current != NULL) {
		printTree(Current->LeftChild);
		printTree(Current->RightChild);

		cout << hex;
		cout <<setiosflags(ios::fixed | ios::showpoint | ios::internal);
		cout << setiosflags(ios::unitbuf | ios::right);
		cout << "\""<< setw(1) << Current->Character<<"\"";
		if (Current->Character=='\0') cout << " ";
		cout << setiosflags(ios::left);
		cout << setw(12) << setprecision(7)	<< Current->Probability << "    ";
		cout << setw(17) << setfill(' ') << Current->CodeBit;
		cout << " " << hex << Current;
		cout << " " << hex << Current->Parent << " " << Current->LeftChild;
		cout << " " << Current->RightChild << dec << endl;
		}
	return;
	}
	
//==========================================					
void Tree::assignBits(){
	if (Root != NULL) {
		assignBits(Root->LeftChild,"0");
		assignBits(Root->RightChild,"1");
		}
	return;
	}
	
//==========================================					
void Tree::assignBits(Symbol *Current, char *BitSet){
	char BitBuffer[16];
	BitBuffer[0]='\0';
	strcat(BitBuffer,BitSet);	

	if (Current != NULL) {
		strcpy(Current->CodeBit,BitSet);
		assignBits(Current->LeftChild,strcat(BitBuffer,"0"));
		
		BitBuffer[0]='\0';
		strcat(BitBuffer,BitSet);
		assignBits(Current->RightChild,strcat(BitBuffer,"1"));
		}
	return;
	}

//==========================================					
void Tree::writeTable(ofstream *OUTPUT){
	Symbol *Current=Root;
	if (Root !=NULL) {
		if (Current->Character!='\0'){
			*OUTPUT << Current->Character << " " << Current->CodeBit << endl;
			}
		writeTable(OUTPUT,Current->LeftChild);
		writeTable(OUTPUT,Current->RightChild);
		}
	}
	
//==========================================					
void Tree::writeTable(ofstream *OUTPUT,Symbol* Current){
	if (Current !=NULL) {
		if (Current->Character!='\0')
			*OUTPUT << Current->Character << " " << Current->CodeBit << endl;
		this->writeTable(OUTPUT,Current->LeftChild);
		this->writeTable(OUTPUT,Current->RightChild);
		}
	}