二叉树的层次遍历、哈夫曼树及哈夫曼编码的建立
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); }
相关文章推荐
- 二叉树的建立与前、中、后、层次遍历
- UVa 122 Trees on the level(链式二叉树的建立和层次遍历)
- java实现二叉树的建立,前中后序遍历,层次遍历,深度,节点个数等
- 二叉树各种相关操作(建立二叉树、前序、中序、后序、求二叉树的深度、查找二叉树节点,层次遍历二叉树等)(C语言版)
- 二叉树先序后序递归建立,前中后序层次非递归遍历,以及统计叶子结点个数以及树的深度
- 数据结构--java实现二叉树的先序、中序、后序、层次遍历及根据先序中序建立二叉树
- 二叉树的建立及遍历(先序遍历、中序遍历、后续遍历、层次遍历)
- python实现二叉树的建立以及遍历(递归前序、中序、后序遍历,队栈前序、中序、后序、层次遍历)
- java建立二叉树,递归/非递归先序遍历,递归/非递归中序遍历,层次遍历
- 树的遍历 有后序遍历和中序遍历建立二叉树,并输出层次遍历
- java建立二叉树,递归/非递归先序遍历,递归/非递归中序遍历,层次遍历
- 二叉树的建立&&前中后遍历(递归实现)&&层次遍历
- 数据结构二叉树——建立二叉树、中序递归遍历、非递归遍历、层次遍历
- uva 11234 Expressions(建立二叉树+层次遍历)
- 二叉树采用二叉链表结构表示。设计并实现如下算法:输入某棵二叉树的广义表形式,建立该二叉树,并按层次遍历该二叉树。
- 二叉树建立 以及 bfs层次遍历
- 数据结构二叉树——建立二叉树、中序递归遍历、非递归遍历、层次遍历
- java根据层次遍历建立二叉树
- 建立二叉树,并层次遍历输出
- 二叉树的建立和基础操作<二> —— (层次遍历和计算二叉树的宽度)