久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2859|回復: 0
打印 上一主題 下一主題
收起左側(cè)

哈弗曼樹與哈弗曼編碼

[復制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:51024 發(fā)表于 2014-7-30 14:04 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
上學期學的數(shù)據(jù)結(jié)構(gòu),當時老師給的題目是:

從一文件中讀取字符,分別統(tǒng)計該文件中英文字符ABCD...等26個字母出現(xiàn)的概率,并以各自的概率為權(quán)值,為26個字符建立一棵赫夫曼樹,并對每個字符進行哈弗曼編碼和哈弗曼解碼。


當時課堂檢測時老師要求文件內(nèi)容為AAAAABBBCDFG(反正就是某一個字母頻率高,其他很多字母缺失),結(jié)果我的代碼運行之后就出現(xiàn)階梯一樣的編碼結(jié)果。老師說我代碼哪里錯了。可是這兩天我重新編碼(主要是當初的代碼沒備份,電腦硬盤壞過一次換了資料都沒了),發(fā)現(xiàn)結(jié)果還是這樣的奇怪的階梯。然后我才想明白哈弗曼樹的目的是樹的帶權(quán)長度最小,那么沒有出現(xiàn)過的字母權(quán)都是0,所以它們的編碼長度是沒有意義的。出現(xiàn)這樣的結(jié)果應該是正常的。如果一定要糾結(jié)這個問題,應該再寫一部分判斷權(quán)是否為0,只統(tǒng)計并記錄權(quán)為非0的字母。這里只附上目前的代碼(沒加判斷權(quán)為0的這部分,往后看有空再加,這兩天要復習,就先不玩了)。


#include  

#include  

#include  

#include


#define N  555

#define M  26


typedef struct Node{

    float weight;                //權(quán)值

    int parent;                //父節(jié)點的序號,為0的是根節(jié)點

    int lchild,rchild;         //左右孩子節(jié)點的序號,為0的是葉子節(jié)點

}HTNode,*HuffmanTree;          //用來存儲赫夫曼樹中的所有節(jié)點


typedef char **HuffmanCode;    //用來存儲每個葉子節(jié)點的赫夫曼編碼





void select_minium (HuffmanTree  &HT , int i ,int * min1 , int * min2){

int j=0;int temp;

for (; j <= i;j ++){

if(HT[*min1].parent) //min1對應的父節(jié)點必須為0

(*min1)=j;

else

if(HT[*min2].parent || *min1==*min2)//min2對應的父節(jié)點必須為0且min1min2不相等

(*min2)=j;

else

if (HT[*min2].weight

temp=*min2;

*min2=*min1;

*min1=temp;

}

else if(!HT[j].parent){

if (HT[j].weight <= HT[*min1].weight){

//權(quán)值比最小的還小或相等時,將此時的min1賦給min2,此時的哈弗曼結(jié)點序號付給min1.

*min2 = *min1;

*min1 = j;

}

else if (HT[j].weight < HT[*min2].weight )

//權(quán)值比min1的大,但比min2的小,只需改變min2。。。。。。..

*min2 = j;



}

}

}


HuffmanTree create_HuffmanTree(float *wet,int n,HuffmanTree &HT){



    //一棵有n個葉子節(jié)點的赫夫曼樹共有2n-1個節(jié)點

    int total = 2*n-1;

    HT = (HuffmanTree)malloc((total)*sizeof(HTNode));

    if(!HT){

        printf("HuffmanTree malloc faild!");

        exit(-1);

    }



    int i;



    //HT[0..n-1]中存放需要編碼的n個葉子節(jié)點

    for(i=0;i

HT[i].parent=0;

HT[i].lchild=0;

HT[i].rchild=0;

HT[i].weight=*wet;

wet++;

}//HT[n..2n-2]中存放的是中間構(gòu)造出的每棵二叉樹的根節(jié)點

for(;i

int min1=0;

int min2=0;

//用來保存每一輪選出的兩個weight最小且parent為0的節(jié)點

//每一輪比較后選擇出min1和min2構(gòu)成一課二叉樹,

//最后構(gòu)成一棵赫夫曼樹



select_minium(HT, i, &min1, &min2);//選出兩個weight最小且parent為0的節(jié)點min1,min2

HT[min1].parent=i;

HT[min2].parent=i;

HT[i].lchild=min1;

HT[i].rchild=min2;

//這里左孩子和右孩子可以反過來,構(gòu)成的也是一棵赫夫曼樹,只是所得的編碼不同

HT[i].weight=HT[min1].weight + HT[min2].weight ;

HT[i].parent =0;



}

}


void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, float *wet ,int n){

printf("\nHuffmanCoding...\n");


    //用來保存指向每個赫夫曼編碼串的指針

    HC = (HuffmanCode)malloc((n+1)*sizeof(char *));

    if(!HC){

        printf("HuffmanCode malloc faild!");

        exit(-1);

    }

int i, start, c, f;


for(i = 0; i <= M; i++)


HC[i] = (char *)malloc((M +1)* sizeof(char));




    //臨時空間,用來保存每次求得的赫夫曼編碼串

char cd[M]={0};



    if (!cd){

        printf("code malloc faild!");

        exit(-1);

    }



cd[n-1] = '\0';  //編碼結(jié)束符,亦是字符數(shù)組的結(jié)束標志

    //求每個字符的赫夫曼編碼

for (i = 0; i < n; ++ i){//逐個字符求哈弗曼編碼

start = n -1 ;//編碼結(jié)束符的位置

for (c = i, f = HT[i].parent;f != 0; c =f, f = HT[f].parent)

//從葉子到跟逆向求哈弗曼編碼

if (HT[f].lchild == c )

cd[ -- start] = '0';//左孩子則為0

else

cd[ -- start ] = '1';//右孩子為1

HC[i] = (char *)malloc((n - start+1) * sizeof (char ));//為第i個字符編碼分配空間

strcpy(HC[i],&cd[start]);//從cd復制編碼串到HC

printf("字母%c 的哈弗曼編碼為 %s\n",'A'+i,HC[i]);

}

//free ( cd );

}//HuffmanCoding




void Read_File(char str[N]){//讀取文件內(nèi)容,并將文件中的字符串放在字符數(shù)組str[N]中

FILE *fp;

if((fp=fopen("E:\\VSProjects\\HuffmanTree\\Huffuman\\text.txt","rt"))==NULL){

printf("\nConnot open file!");//如果打開不成功則顯示不能打開文件

getchar();

exit(1);//關閉所有文件,終止正調(diào)用的過程

}

fgets(str,N,fp);

printf("文件內(nèi)容:\n");

    printf("\n%s\n\n",str);

}



void Count(int Cnt[M], float wet[M], char str[N]){

//統(tǒng)計str中ABCD...出現(xiàn)的次數(shù)放在Cnt[M]中,計算頻率作為權(quán)值放在wet[M]中

int i,all_number;

all_number=0;

for (i=0;i

Cnt[i]=0;//計數(shù)初值賦值0

for (i=0;str[i] != '\0';i++){

Cnt[str[i]-'A']++;

all_number++;

}//統(tǒng)計各個字母出現(xiàn)次數(shù)

for (i=0;i

wet[i]= ((float)Cnt[i])/all_number;

}//計算頻率作為權(quán)值放在wet[M]中

//打印輸出各個字母的出現(xiàn)次數(shù)和權(quán)值

for (i = 0 ; i < M ; i ++){

printf("字母%c 出現(xiàn)的次數(shù)是   %d  ,權(quán)值為   %f \n", 'A' + i, Cnt[i] ,wet[i]);

}

}



void decode(HuffmanTree &HT ){//依次讀入電文,根據(jù)哈夫曼樹譯碼

int i,j=0;

char ch[N];

i=2*M-1-1;             //從根結(jié)點開始往下搜索

printf("輸入發(fā)送的編碼:");

gets(ch);

printf("譯碼后的字符為");

while(ch[j]){

  if(ch[j]=='0')

   i=HT[i].lchild;   //走向左孩子

  else

   i=HT[i].rchild;   //走向右孩子

  if(HT[i].lchild==0)  {    //tree[i]是葉結(jié)點

   printf("%c",'A'+i);

  i=2*M-1-1;      //回到根結(jié)點

  }

  j++;

}

printf("\n");

}//decode


void main ( void ){

char str[N];//文件中的字符串放在字符數(shù)組str[N]中

int Cnt[M];//統(tǒng)計各個字母出現(xiàn)次數(shù)放在數(shù)組Cnt[M]中

float wet[M];//頻率作為權(quán)值放在wet[M]中


HuffmanTree HT[2*M-1];//哈弗曼樹的結(jié)點,一共有2*M -1=51個

HuffmanCode HC[M];//哈弗曼編碼


Read_File(str);

//讀取文件內(nèi)容,并將文件中的字符串放在字符數(shù)組str[N]中

Count(Cnt, wet, str);

//統(tǒng)計str中ABCD...出現(xiàn)的次數(shù)放在Cnt[M]中,計算頻率作為權(quán)值放在wet[M]中

create_HuffmanTree(wet, M, *HT );//創(chuàng)建哈弗曼樹

HuffmanCoding(*HT, *HC, wet , M);//哈弗曼編碼

decode( *HT );//哈弗曼譯碼



}


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 久草网址 | 亚洲精品视频免费 | 亚洲精品一区二区三区四区高清 | 男人亚洲天堂 | 污污的网站在线观看 | 一区二区三区电影网 | 亚洲视频在线看 | 成年人在线观看视频 | 中国一级大黄大片 | 久久国产精品99久久久大便 | 亚洲欧美中文日韩在线v日本 | 欧美精品网站 | 波多野结衣一区二区三区在线观看 | 99精品电影 | 欧美精品久久久 | 亚洲精品一区在线观看 | 草在线 | 草樱av | 成人av免费网站 | 91精品国产91 | 国产精品毛片一区二区在线看 | 亚洲一区二区国产 | 国产成人综合在线 | 日韩一区欧美一区 | 三级视频国产 | 免费精品 | 欧美综合国产精品久久丁香 | 国产精品成人av | 欧美国产一区二区 | 色婷婷久久综合 | 国产精品精品久久久 | 亚洲天堂成人在线视频 | 九九亚洲 | 亚洲欧美在线观看 | 古装人性做爰av网站 | 日韩精品一区二区三区免费视频 | 99精品在线免费观看 | 中文字幕 国产精品 | 色花av| 成人免费观看男女羞羞视频 | 国产激情一区二区三区 |