實現思想:
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;
}