一、目的要求
(1)掌握二叉树的存储实现。
(2)掌握二叉树的遍历思想。
(3)掌握二叉树的常见算法的程序实现。
二、实验内容
(1)输入字符序列,建立二叉链表。
(2)中序遍历二叉树:采用递归算法和非递归算法。(最好也能实现先序,后序非递归算法)
(3)求二叉树的高度和叶子个数。
(4) 借助队列实现二叉树的层次遍历。
(5)综合训练:为N个权值设计哈夫曼编码。(选做)
#include <stdio.h>
#include <malloc.h>
#include <math.h>
#define MaxSize 100
#define MaxWidth 40
typedef char ElemType; // 定义数据类型
typedef struct tnode //定义节点
{
ElemType data;
struct tnode *lchild,*rchild; //两个指针指向左右孩子
} BTNode; //节点类型
char result[100]={0}; //记录层次遍历的结果
void CreateBTree(BTNode * &bt,char *str) // 由str创建二叉链bt
{
BTNode *St[MaxSize],*p=NULL;
int top=-1,k,j=0;
char ch;
bt=NULL; //初始化
ch=str[j];
while (ch!='\0') //str未扫描完时循环
{
switch(ch)
{
case '(':top++;St[top]=p;k=1; break; /*为左孩子结点*/
case ')':top--;break;
case ',':k=2; break; /*为孩子结点右结点*/
default:p=(BTNode *)malloc(sizeof(BTNode));p->data=ch;p->lchild=p->rchild=NULL;
if (bt==NULL) /* *p为二叉树的根结点 */
bt=p;
else /*已建立二叉树根结点*/
{ switch(k)
{
case 1:St[top]->lchild=p;break;
case 2:St[top]->rchild=p;break;
}
}
}
j++;
ch=str[j];
}
}
void DispBTree(BTNode *bt) /*以括号表示法输出二叉树*/
{
if (bt!=NULL)
{
printf("%c",bt->data);
if (bt->lchild!=NULL || bt->rchild!=NULL)
{
printf("(");
DispBTree(bt->lchild); /*递归处理左子树*/
if (bt->rchild!=NULL)
printf(",");
DispBTree(bt->rchild); /*递归处理右子树*/
printf(")");
}
}
}
void DispBTree1(BTNode *bt) /*以凹入表示法输出一棵二叉树*/
{
BTNode *St[MaxSize],*p;
int Level[MaxSize][2],top=-1,n,i,width=4;
char type; /*取值L表示为左结点,R表示为右结点,B表示为根结点*/
if (bt!=NULL)
{
top++;
St[top]=bt; /*根结点入栈*/
Level[top][0]=width;
Level[top][1]=2; /*2表示是根*/
while (top>-1)
{
p=St[top]; /*退栈并凹入显示该结点值*/
n=Level[top][0];
switch(Level[top][1])
{
case 0:type='L';break; /*左结点之后输出(L)*/
case 1:type='R';break; /*右结点之后输出(R)*/
case 2:type='B';break; /*根结点之后前输出(B)*/
}
for (i=1;i<=n;i++) /*其中n为显示场宽,字符以右对齐显示*/
printf(" ");
printf("%c(%c)",p->data,type);
for (i=n+1;i<=MaxWidth;i+=2)
printf("━");
printf("\n");
top--;
if (p->rchild!=NULL)
{ /*将右子树根结点入栈*/
top++;
St[top]=p->rchild;
Level[top][0]=n+width; /*场宽增width,即缩width格后再输出*/
Level[top][1]=1; /*1表示是右子树*/
}
if (p->lchild!=NULL)
{ /*将左子树根结点入栈*/
top++;
St[top]=p->lchild;
Level[top][0]=n+width; /*显示场宽增width*/
Level[top][1]=0; /*0表示是左子树*/
}
}
}
}
void levelTraverse(BTNode *bt)
{
BTNode Queue[20];
BTNode *p;
int i=0;
p=bt;/*根指针入队*/
int front=0,rear=0; /*表示队头指针和队尾指针*/
if(p)
{
Queue[rear]=*p;
rear=(rear+1)%20; /*队尾指针加一对20取余,可实现循环队列,合理利用空间*/
while(front!=rear) /*队不空*/
{
*p=Queue[front]; /*出队,将值赋给p*/
printf("%c",p->data);
result[i++]=p->data;
front=(front+1)%20;
if(p->lchild) /*如果p有左子树,将左子树入队*/
{
Queue[rear]=*p->lchild;
rear=(rear+1)%20;
}
if(p->rchild) /*如果p有右子树,将右子树入队*/
{
Queue[rear]=*p->rchild;
rear=(rear+1)%20;
}
}
}
}
int main()
{
int h=0,times=1,r=0,figure,Leaf;//times表示层次,h高度,figure结点个数
BTNode *bt;
CreateBTree(bt,"A(B(D(H,I),E(J,K)),C(F(L),G))"); /*构造二叉树*/
printf("二叉树bt:");
DispBTree(bt);printf("\n");
printf("bt凹入表示:\n");
DispBTree1(bt);printf("\n");
printf("层次遍历:\n");
levelTraverse(bt);
printf("\n");
while(times<=h)//控制输出
{
for(int i=0;i<pow(2.0,h-times);i++)
printf(" ");//控制每行开头的空格
for(int j=0;j<pow(2.0,times-1);j++,r++)//控制每行输出个数
{
if(result[r]!='*')
printf("%c",result[r]);
else
printf(" ");
for(int k=0;k<pow(2.0,h-times+1)-1;k++)
printf(" ");//每行内部空格控制
}
printf("\n");
times++;
}//while
scanf("%d",&h);
}