(1)采用二叉链表结构建立二叉树;
(2)编程实现二叉树的先序、中序、后序和层序遍历;
(3)编程实现:求二叉树的高度和叶的结点个数;
(4)应用实现:哈夫曼编码。
1.建立二叉树和遍历二叉树
#include <iostream>
#define m 100
typedef struct BiTNode{
char data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
typedef struct{
BiTree base;
int front;
int rear;
}SqQueue;
void CreatBiTree(BiTree &T);
void PreOrderTraverse(BiTree T);
void InOrderTraverse(BiTree T);
void PostOrderTraverse(BiTree T);
void Level(BiTree T);
void InitQueue(SqQueue &s);
void EnQueue(SqQueue &s,BiTree T);
BiTree DeQueue(SqQueue &s);
bool IsEmpty(SqQueue s);
using namespace std;
int main(){
BiTree T;
cout<<"先序遍历顺序建立二叉树为:"<<endl;
CreatBiTree(T);
cout<<"先序遍历输出为:"<<endl;
PreOrderTraverse(T);
cout<<endl;
cout<<"中序遍历输出为:"<<endl;
InOrderTraverse(T);
cout<<endl;
cout<<"后序遍历输出为:"<<endl;
PostOrderTraverse(T);
cout<<endl;
cout<<"层序遍历输出为:"<<endl;
Level(T);
cout<<endl;
}
//先序建立二叉树
void CreatBiTree(BiTree &T){
char ch;
cin>>ch;
if(ch=='#'){
T=NULL;
}else if(ch!='#' && ch!='!'){
T=new BiTNode;
T->data=ch;
CreatBiTree(T->lchild);
CreatBiTree(T->rchild);
}
}
//先序遍历:若结点不为空输出根结点数据,再遍历左子树,遍历右子树;
// 若为空就不输出
void PreOrderTraverse(BiTree T){
if(T){
cout<<T->data<<" ";
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
}
//中序遍历:若结点不为空就遍历左子树,输出根结点数据,再遍历右子树;
// 若为空就不输出
void InOrderTraverse(BiTree T){
if(T){
InOrderTraverse(T->lchild);
cout<<T->data<<" ";
InOrderTraverse(T->rchild);
}
}
//后序遍历:若结点不为空就遍历左子树,然后遍历右子树,输出根结点数据;
// 若为空就不输出
void PostOrderTraverse(BiTree T){
if(T){
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
cout<<T->data<<" ";
}
}
//层次顺序遍历:先进先出符合队列,先让第一层结点入队,然后依次入队;
// 依次出队就为层次顺序遍历
void Level(BiTree T){
SqQueue s;
if(T){
InitQueue(s);
EnQueue(s,T);
while(!IsEmpty(s)){
BiTree temp;
temp=DeQueue(s);
cout<<temp->data<<" ";
if(temp->lchild){
EnQueue(s,temp->lchild);
}
if(temp->rchild){
EnQueue(s,temp->rchild);
}
}
}
}
//进队列
void EnQueue(SqQueue &s,BiTree e){
if(s.front==(s.rear+1)%m){
cout<<"队列满了无法入队"<<endl;
}else{
s.base[s.rear]=*e;
s.rear=(s.rear+1)%m;
}
}
//出队列
BiTree DeQueue(SqQueue &s){
BiTree e;
if(s.front==s.rear){
return NULL;
}else{
*e=s.base[s.front];
s.front=(s.front+1)%m;
return e;
}
}
//初始化循环队列
void InitQueue(SqQueue &s){
s.base=new BiTNode[m];
s.front=s.rear=0;
}
bool IsEmpty(SqQueue s){
if(s.front==s.rear){
return true;
}else{
return false;
}
}
2.二叉树高度和叶结点个数
#include <iostream>
typedef struct BiTNode{
char data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
void CreatBiTree(BiTree &T);
int Depth(BiTree T);
int LeafCount(BiTree T);
using namespace std;
int main(){
BiTree T;
cout<<"先序遍历顺序建立二叉树为:"<<endl;
CreatBiTree(T);
cout<<"该二叉树深度为:"<<Depth(T)<<endl;
cout<<"该二叉树叶子结点个数为:"<<LeafCount(T)<<endl;
}
//先序建立二叉树
void CreatBiTree(BiTree &T){
char ch;
cin>>ch;
if(ch=='#'){
T=NULL;
}else if(ch!='#' && ch!='!'){
T=new BiTNode;
T->data=ch;
CreatBiTree(T->lchild);
CreatBiTree(T->rchild);
}
}
//深度
int Depth(BiTree T){
if(T==NULL) return 0;
else{
int x=Depth(T->lchild);
int y=Depth(T->rchild);
if(x>y) return x+1;
else return y+1;
}
}
//叶子结点个数
int LeafCount(BiTree T){
if(T==NULL){
return 0;
}else if(T->lchild==NULL && T->rchild==NULL){
return 1;
}else{
return LeafCount(T->lchild)+LeafCount(T->rchild);
}
}
3.哈夫曼编码
#include<iostream>
#define MAX 1000
using namespace std;
struct node {
char val;
int weight;
int par, lSon, rSon;
}*Tree;
void BuildTree(node* &tree,int n);
void findMin(node*& tree,int maxn, int now);
void showTree(node* &tree, int n, int now,int cnt);
void Code(node* tree,int n);
int main(){
cout<<" 10"<<endl;
cout<<" /"<<" \\"<<endl;
cout<<"d"<<" 6"<<endl;
cout<<" /"<<" \\"<<endl;
cout<<" c"<<" 3"<<endl;
cout<<" /"<<" \\"<<endl;
cout<<" a"<<" b"<<endl;
node* Tree;
int n;
cout<<"输入叶节点个数:"<<endl;
cin >> n;
BuildTree(Tree, n);
cout<<"递归打印哈夫曼树的叶子结点:"<<endl;
showTree(Tree,n,2*n-1,0);
Code(Tree,n);
}
//构造哈夫曼树
void BuildTree(node* &tree,int n)
{
int maxn=2*n;
tree=new node[maxn];
cout<<"请输入"<<n<<"个叶子结点的值和权值:"<<endl;
for (int i=1;i<maxn;i++)
tree[i].weight=tree[i].par=tree[i].lSon=tree[i].rSon=0;
for (int i=1; i <=n; i++)
cin>>tree[i].val>>tree[i].weight;
cout<<"新建了"<<n-1<<"个结点,它们是:"<<endl;
for (int i=n+1;i<maxn;i++)
findMin(tree,maxn,i);
cout<<"所有的结点为:"<<endl;
for(int i=1;i<maxn;i++){
cout <<"第"<<i<<"个结点的权值为"<<tree[i].weight<<
",左孩子为"<<tree[i].lSon<<",右孩子为"<<tree[i].rSon<<endl;
}
}
//找到两个最小的权值,已被选中过的结点的双亲下标改成新结点的下标
void findMin(node*& tree,int maxn, int now)
{
int a;
int val=9999999;
//在不是双亲的结点中,找权值最小的作为新结点的左孩子
for (int i=1;i<now;i++){
if (!tree[i].par){
if (tree[i].weight < val){
a=i;
val=tree[i].weight;
}
}
}
tree[now].lSon=a;
tree[now].weight+=tree[a].weight;
tree[a].par=now;
val = 9999999;
//在不是双亲的结点中,找权值最小的作为新结点的右孩子
for (int i=1;i<now;i++){
if (!tree[i].par)
if (tree[i].weight < val)
{
a=i;
val=tree[i].weight;
}
}
tree[now].rSon=a;
tree[a].par=now;
tree[now].weight+=tree[a].weight;
cout <<"第"<<now<<"个结点,其权值为"<<tree[now].weight<<",左孩子为"<<tree[now].lSon<<",右孩子为"<<tree[now].rSon<<endl;
}
//递归打印哈夫曼树的叶子结点
void showTree(node* &tree,int n,int now,int cnt)
{
if (tree[now].lSon==0 && tree[now].rSon==0){
cout<<"值为"<<tree[now].val<<"结点的权值为"<<tree[now].weight<<",路径长为"<<cnt<<endl;
}
else{
if (tree[now].lSon != 0){
showTree(tree,n,tree[now].lSon,cnt+1);
}
if (tree[now].rSon != 0){
showTree(tree, n, tree[now].rSon,cnt+1);
}
}
}
//哈夫曼树编码
string HC[MAX];//哈夫曼编码数组
void Code(node* tree,int n)
{
int start;
char cd[n];
string HC[n+1]="";
cd[n-1]='\0';
//给所有叶子结点编码
for (int i=1;i<=n;i++){
start=n-1;
int c=i;
int f=tree[i].par;
while(f!=0){
--start;
if(tree[f].lSon==c) cd[start]='0';
else cd[start]='1';
c=f;
f=tree[f].par;
}
for(int j=0;j<n-start-1;j++){
HC[i]+=cd[start+j];
}
delete cd;
}
//打印编码
cout<<"左孩子编码为0,右孩子编码为1"<<endl;
for (int i=1;i<=n;i++){
cout<<"第"<<i<<"个结点的编码为"<<HC[i]<<endl;
}
}