1. 程式人生 > >C++構建哈夫曼樹,並輸出哈夫曼編碼

C++構建哈夫曼樹,並輸出哈夫曼編碼

Huffman tree

//輸出Huffman編碼
本程式實現瞭如何將一串字串輸出為Huffman編碼

VER       ||      1.0
DATE      ||      15/11/2017
AUTHER    ||      WUD

比輸入字串agdfaghdabsba

通過字串的處理可以知道其中每個字元出現的次數

字元a出現了4次
字元g出現了2次
字元d出現了2次
字元b出現了2次
字元f出現了1次
字元h出現了1次
字元s出現了1次

然後構建Huffman樹,得到每個字元對應的Huffman編碼

字串的每個字串的huffman編碼為:
a 10
g 011
d 110
b 111
f 000
h 001
s 010

最後得到整個字串的Huffman編碼

整個字串的Huffman編碼為:
10011110000100110011101011101011110

#include<iostream>
#include<string>
#include <windows.h>
#include<stdio.h>
using namespace std;


/*
    --------------------------

    VER       ||      1.0
    DATE      ||      15/11/2017
    AUTHER    ||      WUD

    --------------------------
*/
struct huffTree{ int parent; int lchild; int rchild; int weight; string flag; }; struct Lowest_Node{ char ch; int ch_num; }; void ShowProgram() { HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED); int
j; for(j=0; j<27; j++){ printf("-"); Sleep(1);} printf("\n"); printf("VER || 1.0\n"); printf("DATE || 15/11/2017\n"); printf("AUTHER || WUD\n"); for(j=0; j<27; j++){ printf("-"); Sleep(1); } printf("\n"); Sleep(200); } void coding(int length, huffTree tree[], int n, int &a, int &b){ int i; int r,s; r=s=length; for(i=0;i<n;i++){ if((tree[i].weight<r)&&(tree[i].parent==-1)){ r=tree[i].weight; a=i; } } for(i=0;i<n;i++){ if((tree[i].weight<s)&&(i!=a)&&(tree[i].parent==-1)){ s=tree[i].weight; b=i; } } } void frequency(string str){ int length = str.length(); //長度 Lowest_Node *node=new Lowest_Node[length]; //宣告最0節點 int i,j; //迴圈因子 for(i=0;i<length;i++){ node[i].ch_num = 0; //初始化頻度 } int char_type_num = 0; //初始為0種字元 for(i=0;i<length;i++){ //迴圈整個字串 for(j=0;j<char_type_num;j++){ if(str[i]==node[j].ch||(node[j].ch>='a'&&node[j].ch<='z'&&str[i]+32==node[j].ch)) break;} if(j<char_type_num){node[j].ch_num++;} else{ if(str[i]>='A'&& str[i]<='Z') node[j].ch=str[i]+32; else node[j].ch = str[i]; node[j].ch_num++; char_type_num++; } } //按頻度從大到小排序 for(i=0;i<char_type_num;i++){ for(j=i;j<char_type_num;j++){ if(node[j].ch_num<node[j+1].ch_num){//如果前一個小於後一個,交換 int temp; //臨時頻度 char ch_temp; //臨時字元 temp=node[j].ch_num; ch_temp=node[j].ch; node[j].ch_num=node[j+1].ch_num; node[j].ch=node[j+1].ch; node[j+1].ch_num=temp; node[j+1].ch=ch_temp; } } } for(i=0;i<char_type_num;i++){ //列印字元頻度 cout<<"字元"<<node[i].ch<<"出現了"<<node[i].ch_num<<"次"<<endl;} huffTree *huff = new huffTree[2*char_type_num-1];//宣告需位於確定char_type_num值後 huffTree temp; string *code = new string[2*char_type_num-1]; for(i=0;i<2*char_type_num-1;i++){ //節點初始化 huff[i].parent=-1; huff[i].lchild=-1; huff[i].rchild=-1; huff[i].flag=-1; } for(j=0;j<char_type_num;j++){ //將排序後的第0級節點權重賦值給樹節點 huff[j].weight = node[j].ch_num; } int min1,min2; for(int k=char_type_num;k<2*char_type_num-1;k++){ //賦值0級以上的節點 coding(length,huff,k,min1,min2); huff[min1].parent=k; huff[min2].parent=k; huff[min1].flag="0"; huff[min2].flag="1"; huff[k].lchild=min1; huff[k].rchild=min2; huff[k].weight=huff[min1].weight+huff[min2].weight; } for(i=0;i<char_type_num;i++){ temp = huff[i]; while(1){ code[i]=temp.flag+code[i]; temp =huff[temp.parent]; if(temp.parent==-1)break; } } cout<<"字串的每個字串的huffman編碼為:"<<endl; for(i=0;i<char_type_num;i++){ cout<<node[i].ch<<" "<<code[i]<<endl; } cout<<"整個字串的Huffman編碼為:"<<endl; for(i=0;i<length;i++){ for(j=0;j<char_type_num;j++){ if(str[i]==node[j].ch) cout<<code[j]; } } //釋放記憶體 delete[] node; node=NULL; delete[] huff; huff=NULL; delete[] code; code = NULL; } int main(){ ShowProgram(); int length=0; //字串長度; string str; //目標字串; cout<<"請輸入字串:"; cin>>str; frequency(str); //求各個字串的頻度 return 0 ; }