Board logo

标题: C++ 二叉树的创建 层序遍历 以及 哈夫曼树的编译码实现 [打印本页]

作者: 苹果也疯狂    时间: 2014-6-16 12:57     标题: C++ 二叉树的创建 层序遍历 以及 哈夫曼树的编译码实现

//声明类BiTree及定义结构BiNode,文件名为bitree.h

<IMG style="PADDING-BOTTOM: 0px; BORDER-RIGHT-WIDTH: 0px; LIST-STYLE-TYPE: none; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px; border-image: initial" title="C++ 二叉树的创建 层序遍历 以及 哈夫曼树的编译码实现" name=image_operate_35811398500362098 alt="C++ 二叉树的创建 层序遍历 以及 哈夫曼树的编译码实现" src="http://s11.sinaimg.cn/mw690/0026ZEdigy6IpofFCAO6a&690" width=606 height=450 action-type="show-slide" action-data="http%3A%2F%2Fs11.sinaimg.cn%2Fmw690%2F0026ZEdigy6IpofFCAO6a%26690" real_src="http://s11.sinaimg.cn/mw690/0026ZEdigy6IpofFCAO6a&690">




//定义类中的成员函数,文件名为bitree.cpp
<IMG style="PADDING-BOTTOM: 0px; BORDER-RIGHT-WIDTH: 0px; LIST-STYLE-TYPE: none; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px; border-image: initial" title="C++ 二叉树的创建 层序遍历 以及 哈夫曼树的编译码实现" name=image_operate_55931398500471570 alt="C++ 二叉树的创建 层序遍历 以及 哈夫曼树的编译码实现" src="http://s9.sinaimg.cn/mw690/0026ZEdigy6IpogvbWUb8&690" action-type="show-slide" action-data="http%3A%2F%2Fs9.sinaimg.cn%2Fmw690%2F0026ZEdigy6IpogvbWUb8%26690" real_src="http://s9.sinaimg.cn/mw690/0026ZEdigy6IpogvbWUb8&690">
注意该创建思路是根据前序遍历的思路创建的 ,所以输入的时候要按前序遍历的顺序输入,并且每个叶子后面都要跟两个#。这样才能输入结束。




递归算法的我就不说了,很简单。


仅说说层序遍历:
用一个队列保存被访问的当前节点的左右孩子以实现层序遍历。因为层序遍历的思想是先访问的节点的左右孩子节点也要先访问。这类似于队列的先进先出的思想。




1.要用一个队列先进先出),存放树结点的指针,可以自已定义一个队列
算法:
1.从根结点开始,初始先把根结点队列
2. 如果队列中结点为空,则程序结束;
3. 从队列中取出一节点作为被访问的节点,出列并显示它的数据;并把它非空的左右子树
放到队列中;
4.回到2循环

<IMG style="PADDING-BOTTOM: 0px; BORDER-RIGHT-WIDTH: 0px; LIST-STYLE-TYPE: none; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px; border-image: initial" title="C++ 二叉树的创建 层序遍历 以及 哈夫曼树的编译码实现" name=image_operate_31111398505994194 alt="C++ 二叉树的创建 层序遍历 以及 哈夫曼树的编译码实现" src="http://s13.sinaimg.cn/mw690/0026ZEdizy6IpuBPA1S3c&690" real_src="http://s13.sinaimg.cn/mw690/0026ZEdizy6IpuBPA1S3c&690">





//二叉树的主函数,文件名为bitreemain.cpp


<IMG style="PADDING-BOTTOM: 0px; BORDER-RIGHT-WIDTH: 0px; LIST-STYLE-TYPE: none; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px; border-image: initial" title="C++ 二叉树的创建 层序遍历 以及 哈夫曼树的编译码实现" name=image_operate_96721398500498929 alt="C++ 二叉树的创建 层序遍历 以及 哈夫曼树的编译码实现" src="http://s12.sinaimg.cn/mw690/0026ZEdigy6IpooREqT3b&690" real_src="http://s12.sinaimg.cn/mw690/0026ZEdigy6IpooREqT3b&690">







<IMG style="PADDING-BOTTOM: 0px; BORDER-RIGHT-WIDTH: 0px; LIST-STYLE-TYPE: none; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px; border-image: initial" title="C++ 二叉树的创建 层序遍历 以及 哈夫曼树的编译码实现" name=image_operate_75011398499699198 alt="C++ 二叉树的创建 层序遍历 以及 哈夫曼树的编译码实现" src="http://s16.sinaimg.cn/mw690/0026ZEdigy6Ipmy1QQL2f&690" real_src="http://s16.sinaimg.cn/mw690/0026ZEdigy6Ipmy1QQL2f&690">



下面的代码贴到新浪博客上好像有点问题,不过大致可以看出算法思路就行了。反正我是跑通了,见后面截图<IMG style="PADDING-BOTTOM: 0px; LINE-HEIGHT: 1.5; BORDER-RIGHT-WIDTH: 0px; LIST-STYLE-TYPE: none; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px; border-image: initial" title="C++ 二叉树的创建 层序遍历 以及 哈夫曼树的编译码实现" alt="C++ 二叉树的创建 层序遍历 以及 哈夫曼树的编译码实现" src="http://www.sinaimg.cn/uc/myshow/blog/misc/gif/E___6724EN00SIGG.gif" real_src="http://www.sinaimg.cn/uc/myshow/blog/misc/gif/E___6724EN00SIGG.gif" type="face">




//哈夫曼树算法
#include
#include
#define m 2*n-1
using namespace std;
const int float_max=1000;
typedef int datatype;
typedef struct
{
int weight; //定义权重
int parent; //定义双亲在向量中的下标
int lchild,rchild; //定义左右子树
} HFnode, * hftree;


void InitHuffmanTree(hftree& T,int n)  
//无双亲,即为根结点,尚未合并过,左右孩子指针置为-1
{



int i;

T=new HFnode[m];



for(i=0;i



{







T.weight=0;







T.parent=-1;







T.lchild=-1;







T.rchild=-1;



}
}


void Select(hftree& T,int i,int &p1, int &p2)
{

int j;

int small1,small2;

small1=small2=float_max; //float_max为float类型的最大值,small1 是最小权,small2是次小权。
  

for(j=0;j<=i-1;j++)
{
if(T[j].parent!=-1) continue;//不考虑已合并过的点
if(T[j].weight //修改最小权和次小权及位置
{
small2=small1;
small1=T[j].weight;
p2=p1;
p1=j;
}
else if(T[j].weight //修改次小权及位置
{
small2=T[j].weight;
p2=j;
}
}

}



//哈夫曼树的构造
void huffman(hftree &T,int n)
{
int i,p1,p2;


InitHuffmanTree(T,m);

for(i=0;i
{
cin>>T.weight;  
//输入n个叶子的权
}


for(i=n;i //进行n-1次合并,产生n-1个新结点
{

Select(T,i,p1,p2);

T[p1].parent=T[p2].parent=i; //新根
T.parent=-1;
T.lchild=p1;
T.rchild=p2;
T.weight=T[p1].weight+T[p2].weight; //新结点的权值为最小权与次小权之和
}
}


/
typedef struct
{



char ch;



char * bits;
}CodeNode, * HFCode;



void CreateHuffmanCode(hftree &T,HFCode &HC,int n)
{



int i;



int start;



int c;



int p;



char*cd;



char q;



HC=new CodeNode[n];



cd=new char[n];



cd[n-1]='\0';




for(i=0;i



{







cin>>q;







HC.ch=q;







start=n-1;  //从最后一个节点开始














c=i;






  







while(T[c].parent!=-1) //从字符结点回溯,直至根结点







{










p=T[c].parent;


--start;










cd[start]=(T[p].lchild==c)?'0':'1';  //左孩子编码为0 ,右孩子编码为1










c=p;







}
HC.bits = new char[n-start]; //为第i个字符编码分配空间







strcpy(HC.bits,&cd[start]);



}


  



delete cd;
}



void OutputHuffmanCode(HFCode &HC,int n)
{



int i;



for(i=0;i



{







cout<<HC.ch<<""<<HC.bits<<endl;



}
}



void Decoding(hftree &T, HFCode &HC,int n, string Str)
{

int p = m-1;
int pos=0;
while (Str[pos])
{



if (Str[pos] == '0') p = T[p].lchild;



else p = T[p].rchild;  


  








if(T[p].lchild==-1 && T[p].rchild==-1 )



{






cout<<HC[p].ch;







p = m-1;  



}
pos++;
}
}



int main()
{
int i,n;
cout<<"输入字符个数:";


cin>>n;
hftree T;  //哈夫曼树向量
cout<<"  



欢迎测试!!!!  
"<<endl;
cout<<"----------测试开始-----------"<<endl;
cout<<"首先调用哈夫曼树构造的函数:huffman"<<endl;
cout<<"按下标顺序输入叶子的权重:"<<endl;
for(i=0;i
cout<<i<<' ';
cout<<endl;
huffman(T,n);
cout<<"输出合并后的哈夫曼树的所有结点:"<<endl;
for(i=0;i
cout<<i<<"  ";
cout<<endl;

for(i=0;i
{
cout<<T.weight<<" ";
}
cout<<endl;

HFCode HC;  
cout<<"请输入n个需要编码的字符:"<<endl;
CreateHuffmanCode(T,HC,n);

cout<<"哈夫曼编码:"<<endl;
OutputHuffmanCode(HC,n);


string Str;
cout<<"请输入要译码的二进制串"<<endl;   
cin>>Str;
cout<<"哈夫曼译码:"<<endl;

Decoding(T,HC,n,Str);
system("pause");
return 0;
}

<IMG style="PADDING-BOTTOM: 0px; BORDER-RIGHT-WIDTH: 0px; LIST-STYLE-TYPE: none; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px; border-image: initial" title="C++ 二叉树的创建 层序遍历 以及 哈夫曼树的编译码实现" alt="C++ 二叉树的创建 层序遍历 以及 哈夫曼树的编译码实现" src="http://s10.sinaimg.cn/mw690/0026ZEdigy6It2ImCaR49&690" width=434 height=367 action-type="show-slide" action-data="http%3A%2F%2Fs10.sinaimg.cn%2Fmw690%2F0026ZEdigy6It2ImCaR49%26690" real_src="http://s10.sinaimg.cn/mw690/0026ZEdigy6It2ImCaR49&690">
具体可以应用到解压缩上,就是对文件里的内容进行编解码,我也试了一遍都OK。






欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0