數據結構實習Huffman編譯碼器(二)

實現思想:

1.首先分析輸入的報文,得到各個字符出現的次數和概率,將出現次數作爲權重構建哈夫曼樹

2.構造huffman樹,並動態顯示Huffman樹的生成過程

3,對每個字符進行編碼

4.對字符串編譯碼

5,Socket編程實現通信(重點學習)

界面:




關鍵代碼:

1.

 enum { IDD = IDD_HUFFMAN_DIALOG };
 CListCtrl m_plist;
 CString m_mes;


 

——————————————————

m_plist.InsertColumn( 0, "字符", LVCFMT_LEFT, 40 );//插入列
 m_plist.InsertColumn( 1, "次數", LVCFMT_CENTER, 40 );//插入列
 m_plist.InsertColumn( 2, "概率", LVCFMT_CENTER, 60 );//插入列
 m_plist.InsertColumn( 3, "hfm編碼", LVCFMT_CENTER, 100 );//插入列


 

————————————————————

int CHuffmanDlg::Probability(CString str)//統計每個字符出現概率,返回不同字符個數
{
 CString pro;//存儲字符概率
 if (str==""){MessageBox("輸入報文爲空!"); return 0;}
 int StrLength=str.GetLength();//字符串總長
 int i=0,j=0;
 CString temp;
 while (str!="")
 { 
  temp.Format(_T("%c"), str[0]);;
  m_plist.InsertItem(i,temp);//字符
  j=str.Remove(str[0]);
  temp.Format(_T("%d"),j);//字符出現次數
  m_plist.SetItemText(i,1,temp);
  temp.Format(_T("%3f"),(double)j/StrLength);
  m_plist.SetItemText(i,2,temp);//字符出現概率
  i++;
 }
 return i;


2.huffman樹和節點的數據結構定義

typedef struct HuffmanNode                                             
{
	int weight;//權值
	char character;//存放字符
	bool isLeaf;//是否葉子節點
	int createSort;   //用於標記節點創建順序
	int position;   //用於記錄節點在樹中的位置。以完全二叉樹計算的
	HuffmanNode *leftChild,*rightChild,*parent;//三叉鏈表指針
	HuffmanNode():leftChild(NULL),rightChild(NULL),parent(NULL){}
	HuffmanNode(int elem,char ch,HuffmanNode* left = NULL, HuffmanNode* right = NULL, HuffmanNode* ptr = NULL ):weight(elem),character(ch),
		leftChild(left), rightChild(right), parent(ptr){}
	bool operator <=(HuffmanNode& R){return weight <= R.weight;}
	bool operator > (HuffmanNode& R){return weight > R.weight;}
	HuffmanNode* sAddress;
	int visited;//訪問標記,編碼時使用
	CString hfmCode;
}HuffmanNode;

class HuffanTree  
{
public:
	int createSort;
	void mergeTree(HuffmanNode & ht1, HuffmanNode & ht2, HuffmanNode*& parent);
	void enCode(int n,CListCtrl *list);   //對哈弗曼樹進行編碼  ,n個葉子節點
	void CreateHfmTree(int n,CListCtrl * list);//創建哈弗曼樹
	HuffanTree();
	virtual ~HuffanTree();
	
	HuffmanNode *huffNode[256];  //申請編碼空間,最多有256中不同字符
	HuffmanNode* root;
	int codeTotal;     //編碼節點的個數,即需要多少個huffmanNode
	HuffmanNode* rootFull;   //繪畫時候需要的滿二叉樹
};

創建huffman樹:

void HuffanTree::CreateHfmTree(int n,CListCtrl *list)
{
	codeTotal = n;    //總共需要n個節點,因爲共出現了n個不重複的字符
	createSort=1;
	int i,elem;//elem爲字符出現次數,置爲權值
	char ch;//字符
	MinHeap hp(n);//初始化最小堆
	CString str;
	HuffmanNode *parent,first,second,*work;
	
	for (i=0;i<codeTotal;i++)//構造n個葉子節點
	{
		elem=_ttoi(list->GetItemText(i,1));//CString轉爲int
		ch= list->GetItemText(i,0)[0];
		work = new HuffmanNode;
		work->weight = elem;
		work->character = ch;
		work->position = i;
		work->isLeaf = true;
		work->visited=0;//葉子節點記錄爲未訪問
		work->leftChild = NULL;
		work->rightChild = NULL;
		work->parent = NULL;
		work->sAddress = work;
		hp.Insert(*work);
		//huffNode[i]=work;
	}
	int leafNum=0;
	for(i = 0; i < n-1; i++){
		
		hp.RemoveMin(first);

		hp.RemoveMin(second);
		mergeTree(first,second,parent);
		if (first.rightChild==NULL&&first.leftChild==NULL)
		{
			huffNode[leafNum++]=first.sAddress;
		}
		if (second.rightChild==NULL&&second.leftChild==NULL)//記錄葉子節點
		{
			huffNode[leafNum++]=second.sAddress;
		}
		hp.Insert(*parent);
	}
	root = parent;
    
	root->createSort = createSort;//最後創建
}


 

void HuffanTree::mergeTree(HuffmanNode &ht1, HuffmanNode  &ht2, HuffmanNode* & parent)
{
	parent = new HuffmanNode;
	parent->leftChild = ht1.sAddress;
	parent->rightChild = ht2.sAddress;
	parent->weight = ht1.weight + ht2.weight;
	parent->position = -1;         //給父節點的位置賦-1,父節點不是要編碼的節點
	parent->character = '#';       //給父節點一個標誌
	parent->visited=1;              //父節點標記爲已訪問
	ht1.sAddress->parent = ht2.sAddress->parent = parent;
	ht1.sAddress->createSort = createSort++;
	ht2.sAddress->createSort = createSort++;
	parent->isLeaf = false;
	parent->sAddress=parent;
}



 

發佈了27 篇原創文章 · 獲贊 11 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章