<html>

<head><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- MyFirstUnitAd -->
<ins class="adsbygoogle"
     style="display:inline-block;width:970px;height:250px"
     data-ad-client="ca-pub-5778386704669218"
     data-ad-slot="1503492166"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

<meta http-equiv="Content-Language" content="zh-cn">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Huffman</title>
</head>

<body>



<p align="left"><span lang="en-ca"><font size="6" color="#FF0000"><b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
Huffman Coding</b></font></span></p>

<div align="left">
  <pre><b><font color="#ff0000" size="5">A. <span lang="en-ca">First</span> Edition</font></b></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>This is a small practice for data structure of famous &quot;Huffman coding&quot; which is a wish lingering in my mind long</b></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>before.</b></span></pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">B</span>.<span lang="en-ca"><a name="problem"></a>The problem</span></font></b></pre>
</div>
<div align="left">
  <font FACE="TimesNewRomanPSMT">
  <p ALIGN="LEFT"><span lang="en-ca"><b>Huffman Encoding is a very basic 
  compressing algorithm which is considered to be known to every</b></span></p>
  <p ALIGN="LEFT"><span lang="en-ca"><b>computer science student. So, I always 
  want to write it myself, even with sample code in hand.</b></span></p>
  </font>
  <p ALIGN="LEFT">กก</div>
<div align="left">
  <b><font color="#ff0000" size="5"><span lang="en-ca"><a name="explain"></a>C</span>.<span lang="en-ca">The
  </span></font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>idea of 
  program</b></font></span></div>
<div align="left">
  กก</div>
<div align="left">
  <pre><font face="TimesNewRomanPSMT"><b>There<span lang="en-ca"> is little to mention except that Mr. Shaffer preferred to make two different classes of internal and leaf </span></b></font></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b><font face="TimesNewRomanPSMT">nodes.</font></b></span></pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5">D.<span lang="en-ca"><a name="Method"></a>The </span>major functions</font></b></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b><font face="TimesNewRomanPSMT">I overloaded the operator + and ++ of class Huffnode.</font></b></span></pre>
</div>
<div align="left">
  <pre>กก</pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">E</span>.</font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>Further improvement</b></font></span></pre>
</div>
<div align="left">
  <pre>กก</pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">F</span>.</font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>File listing</b></font></span></pre>
</div>
<div align="left" style="width: 898; height: 86">
  <pre><font size="3"><b><span lang="en-ca">1. Huffman</span>.<span lang="en-ca">h</span></b></font></pre>
  <pre><span lang="en-ca"><font size="3"><b>2</b></font></span><font size="3"><b><span lang="en-ca">. Huffman</span>.<span lang="en-ca">cpp</span></b></font></pre>
  <pre><span lang="en-ca"><font size="3"><b>3</b></font></span><font size="3"><b><span lang="en-ca">. </span>main.cpp (main)</b></font></pre>
  <pre><span lang="en-ca"><font size="3" color="#FF0000"><b>file name: Huffman</b></font></span><font size="3" color="#FF0000"><b>.<span lang="en-ca">h</span></b></font></pre>
  <pre>#ifndef HUFFMAN_H
#define HUFFMAN_H

#include &lt;stdio.h&gt;


template&lt;class T&gt;
class Huffnode
{
private:
	T element;
	Huffnode&lt;T&gt;* l;
	Huffnode&lt;T&gt;* r;
	int freq;
	char* path;
	//unsigned int bit;
	int length;
	bool isInternal;
public:
	int getLength(){return length;}
	//unsigned int getBit(){return bit;}
	Huffnode&lt;T&gt;* left(){return l;}
	Huffnode&lt;T&gt;* right(){return r;}
	int getFreq(){return freq;}
	T getElem(){return element;}
	void setPath(const char* str);
	char* getPath(){return path;}
	bool internal(){return isInternal;}
	void operator++();
	Huffnode(int weight);//constructor for internal
	Huffnode(T elem, int frequency);//constructor for leaf
	Huffnode&lt;T&gt;* operator+(Huffnode&lt;T&gt;&amp; other);
	//static Huffnode&lt;T&gt;* root;
};


const int AlphaNumber=128;

class Huffman
{
private:
	Huffnode&lt;char&gt;* nodes[AlphaNumber];
	//Huffnode&lt;char&gt;* lists[AlphaNumber];
	Huffnode&lt;char&gt;* root;
	void initialize();
	void swapNode(Huffnode&lt;char&gt;* lists[], int i, int j);
	void insertList(Huffnode&lt;char&gt;* lists[], Huffnode&lt;char&gt;* ptr, int length);
	void assignPath();
	void sortList(Huffnode&lt;char&gt;* lists[], int length);
	void traverse(Huffnode&lt;char&gt;* ptr, char* pathStr);
	void traverse(Huffnode&lt;char&gt;* ptr);
public:
	Huffman();
	~Huffman();
	void readFile(const char* fileName);
	void buildTree();
	void compress(const char* sourceFile);
	void display();
};

/*
template&lt;class T&gt;
Huffnode&lt;T&gt;* Huffnode&lt;T&gt;::root=NULL;
*/

template&lt;class T&gt;
void Huffnode&lt;T&gt;::operator ++()
{
	freq++;
}


template&lt;class T&gt;
void Huffnode&lt;T&gt;::setPath(const char* str)
{	
	//unsigned int temp;
	length=strlen(str);
	path=new char[length+1];
	strcpy(path, str);
	/*
	bit=0;

	for (int index=length-1; index&gt;=0; index--)
	{
		if (str[index]=='1')
		{
			temp=1;
			bit+=temp&lt;&lt;index;
			//bit+=temp;
		}

	}
	*/
}


template &lt;class T&gt;
Huffnode&lt;T&gt;::Huffnode&lt;T&gt;(T elem, int frequency)
{
	isInternal=false;
	element=elem;
	freq=frequency;
	l=r=NULL;
	path=NULL;
}

//internal node
template&lt;class T&gt;
Huffnode&lt;T&gt;::Huffnode&lt;T&gt;(int weight)
{
	freq=weight;
	isInternal=true;
	l=r=NULL;
	path=NULL;
}


template&lt;class T&gt;
Huffnode&lt;T&gt;* Huffnode&lt;T&gt;::operator +(Huffnode&lt;T&gt;&amp; other)
{
	Huffnode&lt;T&gt;* result=new Huffnode&lt;T&gt;(freq+other.freq);
	if (freq&lt;other.freq)
	{
		result-&gt;l=this;
		result-&gt;r=&amp;other;
	}
	else
	{
		result-&gt;l=&amp;other;
		result-&gt;r=this;
	}
	return result;
}

#endif</pre>
  <pre><span lang="en-ca"><font size="3" color="#FF0000"><b>file name: Huffman</b></font></span><font size="3" color="#FF0000"><b>.<span lang="en-ca">cpp</span></b></font></pre>
  <pre>//#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;stdlib.h&gt;
#include &quot;huffman.h&quot;



Huffman::Huffman()
{
	initialize();
}

void Huffman::traverse(Huffnode&lt;char&gt;* ptr)
{
	if (ptr==NULL)
	{
		return;
	}
	//only delete the internal
	if (ptr-&gt;internal())
	{
		traverse(ptr-&gt;left());
		traverse(ptr-&gt;right());
		delete ptr;
	}

}



Huffman::~Huffman()
{
	Huffnode&lt;char&gt;* ptr=root;
	traverse(ptr);
	for (int i=0; i&lt;AlphaNumber; i++)
	{
		delete nodes[i]-&gt;getPath();
		delete nodes[i];
		nodes[i]=NULL;
	}
}


void Huffman::display()
{
	for (int i=0; i&lt;AlphaNumber; i++)
	{
		if (nodes[i]-&gt;getFreq()!=0)
		{
			//display char in form of int, otherwise invisible.
			printf(&quot;char %d is encoded:%s\t&quot;, nodes[i]-&gt;getElem(), nodes[i]-&gt;getPath());
			printf(&quot;the length:%d\n&quot;, nodes[i]-&gt;getLength()); 
				
		}
	}
}


void Huffman::initialize()
{
	for (int i=0; i&lt;AlphaNumber; i++)
	{
		nodes[i]=new Huffnode&lt;char&gt;(i, 0);
		//lists[i]=nodes[i];//initially all nodes are in lists
	}
}

void Huffman::readFile(const char* fileName)
{
	FILE* stream;
	char ch;	
	if ((stream=fopen(fileName, &quot;r&quot;))==NULL)
	{
		printf(&quot;error open file %s\n&quot;, fileName);
		exit(1);
	}
	ch=fgetc(stream);
	while (!feof(stream))
	{		
		nodes[ch]-&gt;operator++();
		ch=fgetc(stream);
	}
}

void Huffman::buildTree()
{
	Huffnode&lt;char&gt;* lists[AlphaNumber];
	Huffnode&lt;char&gt;* ptr;
	int counter=0;
	for (int i=0; i&lt;AlphaNumber; i++)
	{
		if (nodes[i]-&gt;getFreq()!=0)
		{
			lists[counter++]=nodes[i];
		}
	}
	sortList(lists, counter);//must be descending 
	while (counter&gt;1)
	{
		ptr=lists[counter-2]-&gt;operator+(*lists[counter-1]);
		insertList(lists, ptr, --counter);//shrink size by 2, but add one
	}
	root=lists[0];
	assignPath();
}

void Huffman::swapNode(Huffnode&lt;char&gt;* lists[], int i, int j)
{
	Huffnode&lt;char&gt;* hold;
	hold=lists[i];
	lists[i]=lists[j];
	lists[j]=hold;
}

//descending
void Huffman::sortList(Huffnode&lt;char&gt;* lists[], int length)
{
	Huffnode&lt;char&gt;* current;
	
	for (int i=0; i&lt;length-1; i++)
	{
		current=lists[i];
		for (int j=i+1; j&lt;length; j++)
		{
			if (current-&gt;getFreq()&lt;lists[j]-&gt;getFreq())
			{
				swapNode(lists, i, j);
			}
		}
	}
}

//length includes ptr itself
void Huffman::insertList(Huffnode&lt;char&gt;* lists[], Huffnode&lt;char&gt;* ptr, int length)
{
	bool shifting=false;
	Huffnode&lt;char&gt;* hold, *temp;
	for (int i=0; i&lt;length; i++)
	{
		if (!shifting)
		{
			if (ptr-&gt;getFreq()&gt;lists[i]-&gt;getFreq())
			{
				shifting=true;
				hold=ptr;
				//temp=lists[i];
			}
		}
		if (shifting)
		{
			temp=lists[i];
			lists[i]=hold;
			hold=temp;
		}
	}
	//if not find a suitable place, insert at last
	if (!shifting)
	{
		lists[length]=ptr;
	}
}

void Huffman::traverse(Huffnode&lt;char&gt;* ptr, char* pathStr)
{
	int len;
	if (ptr==NULL)
	{
		return;
	}
	len=strlen(pathStr);
	
	//strcpy(pathStr, &quot;ok&quot;);
	if (ptr-&gt;internal())
	{		
		pathStr[len]='0';
		pathStr[len+1]='\0';//grows
		traverse(ptr-&gt;left(), pathStr);
		pathStr[len]='1';
		traverse(ptr-&gt;right(), pathStr);
		pathStr[len]='\0';//restores
	}
	else
	{
		//leaf
		ptr-&gt;setPath(pathStr);
	}
}

void Huffman::assignPath()
{
	Huffnode&lt;char&gt;* ptr=root;
	char buffer[AlphaNumber];
	buffer[0]='\0';
	traverse(root, buffer);
}



</pre>
  <pre><span lang="en-ca"><font size="3" color="#FF0000"><b>file name: main.cpp (main)</b></font></span></pre>
  <pre>#include &quot;huffman.h&quot;



int main()
{
	//unsigned int i=0x80000000;
	//printf(&quot;i is %x\n&quot;, i);

	

	Huffman H;
	H.readFile(&quot;nicktest.txt&quot;);
	H.buildTree();
	H.display();
	
	return 0;
}</pre>
  <pre>
</pre>
</div>
<pre></pre>
<pre></pre>
<pre></pre>
<pre><b><font color="#0000FF"><span lang="en-ca">The result is like following:</span></font></b></pre>

<pre>char 10 is encoded:10010111 the length:8
char 32 is encoded:1101 the length:4
char 40 is encoded:001100010 the length:9
char 41 is encoded:1001001101 the length:10
char 44 is encoded:1011001 the length:7
char 45 is encoded:10010110 the length:8
char 46 is encoded:10100 the length:5
char 48 is encoded:1100 the length:4
char 50 is encoded:1001001110 the length:10
char 57 is encoded:001100011 the length:9
char 65 is encoded:00110100 the length:8
char 67 is encoded:00110101 the length:8
char 68 is encoded:00110011 the length:8
char 69 is encoded:1001001001 the length:10
char 70 is encoded:001100001 the length:9
char 71 is encoded:001100000 the length:9
char 77 is encoded:00110010 the length:8
char 78 is encoded:10010000 the length:8
char 79 is encoded:10010001 the length:8
char 80 is encoded:1001001100 the length:10
char 82 is encoded:1001001111 the length:10
char 83 is encoded:00110110 the length:8
char 84 is encoded:00110111 the length:8
char 86 is encoded:1001001000 the length:10
char 89 is encoded:1001001010 the length:10
char 92 is encoded:1011000 the length:7
char 97 is encoded:10101 the length:5
char 98 is encoded:101110 the length:6
char 99 is encoded:101111 the length:6
char 100 is encoded:0110 the length:4
char 101 is encoded:0111 the length:4
char 102 is encoded:001111 the length:6
char 103 is encoded:001110 the length:6
char 104 is encoded:0000 the length:4
char 105 is encoded:0001 the length:4
char 106 is encoded:1001001011 the length:10
char 108 is encoded:00101 the length:5
char 109 is encoded:00100 the length:5
char 110 is encoded:1111 the length:4
char 111 is encoded:1110 the length:4
char 112 is encoded:10000 the length:5
char 114 is encoded:10001 the length:5
char 115 is encoded:0100 the length:4
char 116 is encoded:0101 the length:4
char 117 is encoded:101101 the length:6
char 118 is encoded:100111 the length:6
char 119 is encoded:10010101 the length:8
char 120 is encoded:10010100 the length:8
char 121 is encoded:100110 the length:6
Press any key to continue</pre>

<pre><span lang="en-ca">			</span></pre>

<pre><span lang="en-ca">				</span> <a href="game24.htm"><img src="picture/back.gif" style="border: medium none" alt="back.gif (341 bytes)" width="32" height="35"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="index.htm"><img src="picture/up.gif" style="border: medium none" alt="up.gif (335 bytes)" width="35" height="32"></a> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img src="picture/next.gif" style="border: medium none" alt="next.gif (337 bytes)" width="32" height="35"> </pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                                   
&nbsp;&nbsp;&nbsp;</p>

</body>

</html>