注釋僅僅是個人意見,隨著理解的加深會越來越接近正確的
/*<br />整個哈夫曼編碼實際上就是設定一個數組,樹有n個節點的話就設立大小為2*n-1 的數組,<br />因為在最理想情況下最多僅有最小的兩個元素處於以編碼後的哈夫曼樹的最低端,這樣的<br />話會用去n-1個空間來儲存編碼後的parent。因此哈夫曼編碼實際上就是把樹存為一元數組<br />打表後尋找的過程(個人思考)<br />*/ </p><p>/*<br /> l儲存樹的樹的節點樹<br /> n=2*l—1在數組的l+1到n位置儲存編碼後的每個非終端節點(非原樹上的節點)<br />*/</p><p>#include<stdio.h><br />#include<stdlib.h><br />#include<string.h><br />struct HtNode<br />{<br /> unsigned int weight;<br /> unsigned int parent,lchild,rchild;<br />}HtNode,*Huffmantree;<br />struct HtNode *Ht,*p;<br />typedef char **Huffmancode; //二維數組,實際上是存每個節點的編碼<br />Huffmancode Hc;<br />char *cd;<br />int n,a1,a2,l;<br />int i,w=0,start,f,c;<br />int select() //我勒個去,怎麼才發現你丫是個窮舉法選出來的最小值,丫真猥瑣<br />{<br /> int k=1,j,flag=0; //有parent的意思就是已經被編碼了<br /> while((Ht+k)->parent!=0) k++; //找啊找的,一直找到還沒被編碼的第一個元素,以它為起點找<br /> for(j=k+1;j<=n;j++,flag=0) //每次迴圈都要把flag置為0<br /> {<br /> if((Ht+j)->parent!=0) flag=1; //如果已經編碼的話,k值不變,j繼續自加迴圈<br /> if((Ht+j)->weight==0) flag=1; //在1到l的階段儲存原樹的節點,l+1到n的階段儲存哈夫曼樹的非終端節點<br /> //則weight為0的話肯定是l+1到n的階段中的沒有存值的節點<br /> if(!flag) //如果未出現上述兩種情況且位置k所存節點的weight不是最小的,<br /> //那麼k的值就要變化,並且從新的k開始再迴圈<br /> {<br /> if(((Ht+j)->weight)<((Ht+k)->weight))<br /> k=j;<br /> }<br /> }<br /> return k;<br />}<br />int main()<br />{</p><p> printf("哈夫曼樹的建立/n");<br /> printf("請輸入葉子(權值)的數目:/n");<br /> scanf("%d",&l);<br /> while(l<1)<br /> {<br /> printf("輸入錯誤,請重新輸入權值 /n");<br /> scanf("%d",&l);<br /> }<br /> if(l==1)<br /> printf("僅有一個元素,無需構造哈夫曼樹");<br /> else {</p><p> n=2*l-1;<br /> //Huffmantree Ht;<br /> Ht=(struct HtNode *)malloc(sizeof(struct HtNode)*(n+1));<br /> //Huffmantree p;<br /> printf("輸入元素權值/n");<br /> for(i=1,p=Ht+1;i<=l;i++,p++)<br /> {<br /> scanf("%d",&w);<br /> while(w<=0)<br /> {<br /> printf("輸入錯啦,請重新輸入/n");<br /> scanf("%d",&w);<br /> }<br /> p->weight=w;<br /> p->lchild=0;<br /> p->rchild=0;<br /> p->parent=0;<br /> }<br /> //輸入樹的各個節點的值<br /> for(i=l+1;i<=n;i++,p++)<br /> {<br /> p->weight=0;<br /> p->lchild=0;<br /> p->rchild=0; //不知道為什麼沒這句<br /> p->parent=0;<br /> }<br /> //初始化準備存非終端節點的值<br /> for(i=l+1;i<=n;i++) //這個<=號很重要,事實上本演算法中都是<=的,從1開始的嘛<br /> {<br /> a1=select(); (Ht+a1)->parent=i;<br /> a2=select(); (Ht+a2)->parent=i;<br /> (Ht+i)->lchild=a1;<br /> (Ht+i)->rchild=a2;<br /> (Ht+i)->weight=(Ht+a1)->weight+(Ht+a2)->weight;<br /> }<br /> //進行存值處理,所謂建立這個樹</p><p> //下面的程式碼完成編碼的任務<br /> Hc=(Huffmancode)malloc((l+1)*sizeof(char *));//二維數組<br /> cd=(char *)malloc(sizeof(char)*l);<br /> cd[l-1]='/0'; //每個數組的最後一個代表結束<br /> for(i=1;i<=l;i++)<br /> {<br /> start=l-1; //從葉子開始逆向求編碼<br /> for(c=i,f=(Ht+i)->parent;f!=0;c=f,f=(Ht+f)->parent)<br /> {<br /> if((Ht+f)->lchild==c)<br /> cd[--start]='0';<br /> else<br /> cd[--start]='1'; }<br /> *(Hc+i)=(char *)malloc(sizeof(char)*(l-start));<br /> strcpy(*(Hc+i),(cd+start)); </p><p> }<br /> printf("對應編碼為/n");<br /> for(i=1;i<=l;i++)<br /> {<br /> printf("%s ",*(Hc+i));<br /> if(i%5==0)<br /> printf("/n");<br /> }<br /> }<br /> system("pause");<br />}<br />/*<br />4<br />12 32 2341 321<br />*/<br />