C++構建哈夫曼樹,並輸出哈夫曼編碼
阿新 • • 發佈:2018-12-22
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 ;
}