您的位置:首页 > 其它

二叉树的层次遍历、哈夫曼树及哈夫曼编码的建立

2017-06-08 21:31 393 查看
#include <stdio.h>
#include <malloc.h>
#define N 100        //叶子结点数
#define M 2*N-1     //树中结点总数
#define MAXN 0x7fffffff
typedef char ElemType;

typedef struct Node
{
ElemType data;
Node *Lchild,*Rchild;
} BiTNode,*BiTree;

typedef struct//哈夫曼树的节点结构类型
{
char data;  //结点值
double weight;  //权重
int parent;     //双亲结点
int lchild;     //左孩子结点
int rchild;     //右孩子结点
} HTNode;

typedef struct//每个节点哈夫曼编码的结构类型
{
char cd
; //存放哈夫曼码
int start;
} HCode;

typedef struct node
{
BiTree data;
node *next;
} Node1,*LinkQueueNode;

typedef struct
{
LinkQueueNode front; //队头指针
LinkQueueNode rear;  //队尾指针
} LinkQueue;

BiTree CreateBiTree();//建立二叉树
int Leaf(BiTree T);//分治法统计叶子节点数目
bool LayerOrder(BiTree bt);//层次遍历二叉树
bool InitQueue(LinkQueue *Q);//链队列初始化
bool EnterQueue(LinkQueue *Q,BiTree x);//入队,将数据元素x插入到队列Q中
bool DeleteQueue(LinkQueue *Q,BiTree *x);//出队,将队列Q的队头元素出队并保存到x所指的存储空间中
bool IsEmpty(LinkQueue *Q);//判断链队列是否为空
void PreOrder(BiTree T);//先序
void InOrder(BiTree T);//中序
void PostOrder(BiTree T);//后序
void CreateHT(HTNode ht[],int n);//构造哈夫曼树
void CreateHCode(HTNode ht[],HCode hcd[],int n);//实现哈夫曼编码
void DispHCode(HTNode ht[],HCode hcd[],int n);//输出哈夫曼编码

int main(void)
{
int count;
int n=7;
char str[8]= {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
double fnum[7]= {0.40,0.30,0.15,0.05,0.04,0.03,0.03};
HTNode ht[M];
HCode hcd
;
for (int i=0; i<n; i++)
{
ht[i].data=str[i];
ht[i].weight=fnum[i];
}
BiTree root=CreateBiTree();
CreateHT(ht,n);
CreateHCode(ht,hcd,n);
printf("先序遍历二叉树:\n");
PreOrder(root);//先序
printf("\n");
printf("中序遍历二叉树:\n");
InOrder(root);//中序
printf("\n");
printf("后序遍历二叉树:\n");
PostOrder(root);//后序
printf("\n");
printf("层次遍历二叉树:\n");
LayerOrder(root);
printf("\n");
count=Leaf(root);
printf("叶子节点的数目为:\n");
printf("%d\n",count);
DispHCode(ht,hcd,n);
printf("\n");
return 0;
}

BiTree CreateBiTree()//建立二叉树
{
ElemType x;
BiTree T;
scanf("%c",&x);
if(x=='#')
T=NULL;
else
{
T=(BiTree)malloc(sizeof(BiTNode));
T->data=x;
T->Lchild=CreateBiTree();
T->Rchild=CreateBiTree();
}
return T;
}

bool LayerOrder(BiTree bt)//层次遍历二叉树
{
LinkQueue Q;
BiTree p;
InitQueue(&Q);
if(bt==NULL)
return false;
EnterQueue(&Q,bt);
whi
aecb
le(!IsEmpty(&Q))
{
DeleteQueue(&Q,&p);
printf("%c ",p->data);
if(p->Lchild)
EnterQueue(&Q,p->Lchild);
if(p->Rchild)
EnterQueue(&Q,p->Rchild);
}
return true;
}

bool InitQueue(LinkQueue *Q)//链队列初始化
{
Q->front=(LinkQueueNode)malloc(sizeof(Node));
if(Q->front!=NULL)
{
Q->rear=Q->front;
Q->front->next=NULL;
return true;
}
else
return false;//溢出
}

bool EnterQueue(LinkQueue *Q,BiTree x)//入队,将数据元素x插入到队列Q中
{
LinkQueueNode NewNode;
NewNode=(LinkQueueNode)malloc(sizeof(Node));
if(NewNode!=NULL)
{
NewNode->data=x;
NewNode->next=NULL;
Q->rear->next=NewNode;
Q->rear=NewNode;
}
else
return false;//溢出
}

bool DeleteQueue(LinkQueue *Q,BiTree *x)//出队,将队列Q的队头元素出队并保存到x所指的存储空间中
{
LinkQueueNode p;
if(Q->front==Q->rear)//表示队列已空
return false;
p=Q->front->next;
Q->front->next=p->next;//队头元素p出队
if(Q->rear==p)//如果队中只有一个元素p,则p出队后成为空队
Q->rear=Q->front;
*x=p->data;
free(p);//释放存储空间
return true;
}

bool IsEmpty(LinkQueue *Q)//判断链队列是否为空
{
return Q->front == Q->rear;

}

int Leaf(BiTree T)//分治法统计叶子节点数目
{
int count;
if(T==NULL)
count=0;
else if(T->Lchild==NULL&&T->Rchild==NULL)
count=1;
else
count=Leaf(T->Lchild)+Leaf(T->Rchild);
return count;
}

void PreOrder(BiTree T)//先序
{
if(T!=NULL)
{
printf("%c ",T->data);
PreOrder(T->Lchild);
PreOrder(T->Rchild);
}
}

void InOrder(BiTree T)//中序
{
if(T!=NULL)
{
InOrder(T->Lchild);
printf("%c ",T->data);
InOrder(T->Rchild);
}
}

void PostOrder(BiTree T)//后序
{
if(T!=NULL)
{
PostOrder(T->Lchild);
PostOrder(T->Rchild);
printf("%c ",T->data);
}
}

void CreateHT(HTNode ht[],int n)//构造哈夫曼树
{
int i,k,lnode,rnode;
double 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=MAXN;            //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[i].weight=ht[lnode].weight+ht[rnode].weight;
ht[i].lchild=lnode;
ht[i].rchild=rnode;
ht[lnode].parent=i;
ht[rnode].parent=i;
}
}

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;
double sum=0,m=0;
int j;
printf("  输出哈夫曼编码:\n"); //输出哈夫曼编码
for (i=0; i<n; i++)
{
j=0;
printf("      %c:\t",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  平均长度=%.2lf\n",1.0*sum/m);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐