哈弗曼树及哈弗曼编码

#include<iostream>

#include<stdio.h>

#include<string.h>

using namespace std;

#define N 50//叶子结点数

#define M 2*N-1//数中结点总数

typedef struct

{

    char data[5];//结点值

    int weight;//权重

    int parent;//双亲结点

    int lchild;//左孩子结点

    int rchild;//右孩子结点

}HTNode;

typedef struct

{

    char cd[N];//存放哈夫曼码

    int start;

}HCode;

void CreateHT(HTNode ht[],int n)//构造哈夫曼树

{

    int i,k,lnode,rnode;

    int min1,min2;

    for(i=0;i<2*n-1;i++)//所有结点的相关域置初值-1

        ht[i].parent=ht[i].lchild=ht[i].rchild=-1;

    for(i=n;i<2*n-1;i++)//构造哈夫曼树

    {

        min1=min2=32767;//lnode和rnode为最小权重的两个结点位置

        lnode=rnode=-1;

        for(k=0;k<=i-1;k++)

            if(ht[k].parent==-1)

            {

                if(ht[k].weight<min1)//只在尚未构造二叉树的结点中查找

                {

                    min2=min1;

                    rnode=lnode;

                    min1=ht[k].weight;

                    lnode=k;

                }

                else if(ht[k].weight<min2)

                {

                    min2=ht[k].weight;

                    rnode=k;

                }

            }

            ht[lnode].parent=i;

            ht[rnode].parent=i;

            ht[i].weight=ht[lnode].weight+ht[rnode].weight;

            ht[i].lchild=lnode;

            ht[i].rchild=rnode;

    }

}

void CreateHCode(HTNode ht[],HCode hcd[],int n)//构造哈夫曼编码

{

    int i,f,c;

    HCode hc;

    for(i=0;i<n;i++)//根据哈夫曼树求哈夫曼编码

    {

        hc.start=n;

        c=i;

        f=ht[i].parent;

        while(f!=-1)//循序知道树根结点

        {

            if(ht[f].lchild==c)//处理左孩子结点

                hc.cd[hc.start–]=’0′;

            else//处理右孩子结点

                hc.cd[hc.start–]=’1′;

            c=f;

            f=ht[f].parent;

        }

        hc.start++;//start指向哈夫曼编码最开始字符

        hcd[i]=hc;

    }

}

void DispHCode(HTNode ht[],HCode hcd[],int n)//输出哈夫曼编码

{

    int i,k;

    int sum=0,m=0,j;

    printf(” 输出哈夫曼编码:\n”);//输出哈夫曼编码

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

    {

        j=0;

        printf(“%s:        “,ht[i].data);

        for(k=hcd[i].start;k<=n;k++)

        {

            printf(” %c”,hcd[i].cd[k]);

            j++;

        }

        m+=ht[i].weight;

        sum+=ht[i].weight*j;

        printf(“\n”);

    }

    printf(“\n 平均长度=%g\n”,1.0*sum/m);

}

void main()

{

    int n=15,i;

    char*str[]={“The”,”of”,”a”,”to”,”and”,”in”,”that”,”he”,”is”,”at”,”on”,”for”,”His”,”are”,”be”};

    int fnum[]={1192,677,541,518,462,450,242,195,190,181,174,157,138,124,123};

    HTNode ht[M];

    HCode hcd[N];

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

    {

        strcpy(ht[i].data,str[i]);

        ht[i].weight=fnum[i];

    }

    printf(“\n”);

    CreateHT(ht,n);

    CreateHCode(ht,hcd,n);

    DispHCode(ht,hcd,n);

    printf(“\n”);

}

这些天明白了一个道理,搞技术也是需要激情的。

也不知道为什么这段过的感觉特别的不爽,也不知道是因为快要考试了,心里没底,而带来的恐惧,还是

搞技术太久,心里想放个假,总之是过的晕晕乎乎,做事情也总是反应迟钝,思维也不快,我爸妈说我是因为睡

不够,但是我觉得我一晚上睡6个半小时,也不算短了。真不知道这样的感觉还要持续多久。

习惯了,下课就做到电脑前,习惯了,晚上一个人回宿舍,习惯了,饿了随便吃点,习惯了,一个人钻研。

当一切开始成为了定式,总觉得生活变的简单。有一些人羡慕我,觉得我有很好的环境学技术。

但是我现在也不觉得我有什么好自满的东西。不过是个再普通不过的走在技术道路上的菜鸟。

心里有千万般的无奈,心里有数不清的彷徨。

我渴望曾经的激情。

其实我也不想说那么多,耽误看帖人的时间,但是心里总有些不吐不快。

师兄总是开玩笑的说我现在开始“淡定了”。

朋友们也觉得我越来越“沉默了”。

现在也不敢想以后会成什么样子,一切都未知。

我不想到了以后“生无可恋,死无可依”(这是一个老程序员的感悟)。

但是我不能停止,停止就是倒退。

好啦,不罗嗦了,下面是我的程序:

 

《哈弗曼树及哈弗曼编码》
#include
<
iostream
>
 

#define
 MAXVALUE 100000


using
 
namespace
 std;

const
 
int
 n
=
4
;
//
叶子节点个数 

//
构造哈夫曼树结点 


typedef 
struct
{

int
 weight;
//
权值 


int
 parent;
//
父节点 


int
 lchild;
//
左子树 


int
 rchild;
//
右子树 


}HNodeType;

HNodeType HFMTree[
2
*
n

1
];
//
结点数 


//
构造哈夫曼编码数组


typedef 
struct
{

int
 bit[n];

int
 start;
}HCodeType;

HCodeType HFMCode[n];

//
创建哈夫曼树 


void
 createHFMTree(HNodeType HFMTree[],
int
 n){

int
 m1,x1,m2,x2;

int
 i,j;

//
初始化


for
(i
=
0
;i
<
2
*
n

1
;i
++
){
   HFMTree[i].weight

=
0
;
   HFMTree[i].parent

=-
1
;
   HFMTree[i].lchild

=-
1
;
   HFMTree[i].rchild

=-
1
;
}
cout

<<

请输入结点权值:

<<
endl; 

for
(i
=
0
;i
<
n;i
++
){                
   cin

>>
HFMTree[i].weight;
}

for
(i
=
0
;i
<
n

1
;i
++
){
   x1

=
x2
=
MAXVALUE;
   m1

=
m2
=
0
;
   

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

if
(HFMTree[j].parent
==-
1
&&
HFMTree[j].weight
<
x1){
     x2

=
x1;
     m2

=
m1;
     x1

=
HFMTree[j].weight;
     m1

=
j;
    }
    

else
 
if
(HFMTree[j].parent
==-
1
&&
HFMTree[j].weight
<
x2){
     x2

=
HFMTree[j].weight;
     m2

=
j;
    }
   }
   HFMTree[m1].parent

=
n
+
i;HFMTree[m2].parent
=
n
+
i;
   HFMTree[n

+
i].weight
=
HFMTree[m1].weight
+
HFMTree[m2].weight;
   HFMTree[n

+
i].lchild
=
m1;
   HFMTree[n

+
i].rchild
=
m2;
}
}

//
转化编码 


void
 createHFMCode(HNodeType HFMTree[],HCodeType HFMCode[]){
HCodeType cd;

int
 i,j,c,p;

for
(i
=
0
;i
<
n;i
++
){
   cd.start

=
n

1
;
   c

=
i;
   p

=
HFMTree[c].parent;
   

while
(p
!=-
1
)
   {
    

if
(HFMTree[p].lchild
==
c)cd.bit[cd.start]
=
0
;
    

else
 cd.bit[cd.start]
=
1
;
    cd.start


;
    c

=
p;
    p

=
HFMTree[c].parent;
   }
   

for
(j
=
cd.start
+
1
;j
<
n;j
++
)
    HFMCode[i].bit[j]

=
cd.bit[j];
   HFMCode[i].start

=
cd.start
+
1
;
}
}

//
主函数 


int
 main()
{

int
 i,j;

//
创建树 


createHFMTree(HFMTree,n);

//
转码 


createHFMCode(HFMTree,HFMCode);
cout

<<
endl;

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

for
(j
=
HFMCode[i].start;j
<=
n

1
;j
++
)
   {
    cout

<<
HFMCode[i].bit[j];
   }
   cout

<<
endl;
}

return
 
0
;
}

《哈弗曼树及哈弗曼编码》

 

这个是雏形,下面我们要实现的功能是,输入一个含有N位A,B,C,D四种字母的字符串。

然后转换成只含有0,1的代码串。之所以要使用哈夫曼树是因为哈夫曼树是最优树。根据权值来实现最短编码。

下面是实现自动转码的程序:

 

《哈弗曼树及哈弗曼编码》
#include
<
iostream
>
 

#define
 MAXVALUE 100000


using
 
namespace
 std;

const
 
int
 n
=
4
;
//
叶子节点个数 


string
 l;

int
 size;

//
构造哈夫曼树结点 


typedef 
struct
{

int
 weight;
//
权值 


int
 parent;
//
父节点 


int
 lchild;
//
左子树 


int
 rchild;
//
右子树 


}HNodeType;

HNodeType HFMTree[
2
*
n

1
];
//
结点数 


//
构造哈夫曼编码数组


typedef 
struct
{

int
 bit[n];

int
 start;
}HCodeType;

HCodeType HFMCode[n];

//
创建哈夫曼树 


void
 createHFMTree(HNodeType HFMTree[],
int
 n){

int
 m1,x1,m2,x2;

int
 i,j;

//
初始化


for
(i
=
0
;i
<
2
*
n

1
;i
++
){
   HFMTree[i].weight

=
0
;
   HFMTree[i].parent

=-
1
;
   HFMTree[i].lchild

=-
1
;
   HFMTree[i].rchild

=-
1
;
}
cout

<<

*******************哈夫曼树字符串最优转码程序***********************

<<
endl; 
cout

<<

请输入一个字符串:(只含有A,B,C,D四种字符,输入回车结束)

<<
endl; 
cin

>>
l;
std::

string
 str(l);
  size

=
str.size();    
  

for
(
int
 i
=
0
;i
<
size;
++
i){   
   

if
(str.at(i)
==

A

)HFMTree[
0
].weight
++
;
   

else
 
if
(str.at(i)
==

B

)HFMTree[
1
].weight
++
;
   

else
 
if
(str.at(i)
==

C

)HFMTree[
2
].weight
++
;
   

else
 
if
(str.at(i)
==

D

)HFMTree[
3
].weight
++
;
   

else

   cout

<<

输入有误!

<<
endl;
   

break
;
   }
}


for
(i
=
0
;i
<
n

1
;i
++
){
   x1

=
x2
=
MAXVALUE;
   m1

=
m2
=
0
;
   

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

if
(HFMTree[j].parent
==-
1
&&
HFMTree[j].weight
<
x1){
     x2

=
x1;
     m2

=
m1;
     x1

=
HFMTree[j].weight;
     m1

=
j;
    }
    

else
 
if
(HFMTree[j].parent
==-
1
&&
HFMTree[j].weight
<
x2){
     x2

=
HFMTree[j].weight;
     m2

=
j;
    }
   }
   HFMTree[m1].parent

=
n
+
i;HFMTree[m2].parent
=
n
+
i;
   HFMTree[n

+
i].weight
=
HFMTree[m1].weight
+
HFMTree[m2].weight;
   HFMTree[n

+
i].lchild
=
m1;
   HFMTree[n

+
i].rchild
=
m2;
}
}

//
转化编码 


void
 createHFMCode(HNodeType HFMTree[],HCodeType HFMCode[]){
HCodeType cd;

int
 i,j,c,p;

for
(i
=
0
;i
<
n;i
++
){
   cd.start

=
n

1
;
   c

=
i;
   p

=
HFMTree[c].parent;
   

while
(p
!=-
1
)
   {
    

if
(HFMTree[p].lchild
==
c)cd.bit[cd.start]
=
0
;
    

else
 cd.bit[cd.start]
=
1
;
    cd.start


;
    c

=
p;
    p

=
HFMTree[c].parent;
   }
   

for
(j
=
cd.start
+
1
;j
<
n;j
++
)
    HFMCode[i].bit[j]

=
cd.bit[j];
   HFMCode[i].start

=
cd.start
+
1
;
}
}

//
主函数 


int
 main()
{

int
 i,j;

//
创建树 


createHFMTree(HFMTree,n);

//
转码 


createHFMCode(HFMTree,HFMCode);
cout

<<
endl;

int
 k
=
65
;

for
(i
=
0
;i
<
n;i
++
)
{
   cout

<<
(
char
)k
<<

的编码:

;
   

for
(j
=
HFMCode[i].start;j
<=
n

1
;j
++
)
   {
    cout

<<
HFMCode[i].bit[j];
   }
   k

++
;
   cout

<<
endl;
}
cout

<<

转码后的字符串为:

<<
endl;
std::

string
 str(l);
  size

=
str.size();    
  

for
(
int
 i
=
0
;i
<
size;
++
i){   
   

if
(str.at(i)
==

A

){
   

for
(j
=
HFMCode[
0
].start;j
<=
n

1
;j
++
)
   cout

<<
HFMCode[
0
].bit[j];
   }
   

else
 
if
(str.at(i)
==

B

){
   

for
(j
=
HFMCode[
1
].start;j
<=
n

1
;j
++
)
   cout

<<
HFMCode[
1
].bit[j];
   }
   

else
 
if
(str.at(i)
==

C

){
   

for
(j
=
HFMCode[
2
].start;j
<=
n

1
;j
++
)
   cout

<<
HFMCode[
2
].bit[j];
   }
   

else
 
if
(str.at(i)
==

D

){
   

for
(j
=
HFMCode[
3
].start;j
<=
n

1
;j
++
)
   cout

<<
HFMCode[
3
].bit[j];
   }
   

else

   cout

<<

输入有误!

<<
endl;
   

break
;
   }
}

return
 
0
;
}

《哈弗曼树及哈弗曼编码》

 

程序本机测试通过,可以放心运行!

转载注明:www.cnblogs.com/shiyangxt

    原文作者:哈夫曼树
    原文地址: https://blog.csdn.net/liang0000zai/article/details/11272305
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞