二叉树的基本操作

1.实现二叉树的各种基本运算7.1,进而完成二叉树的各种遍历应用7.2。(递归和层次遍历)
2.根据表7.8中单词及出现的频度,构造哈夫曼树,输出对应的哈夫曼编码。

1.代码如下:
#include <stdio.h>
#include <malloc.h>
#define MaxSize 100
typedef char ElemType;
typedef struct node
{
	ElemType data;			//数据元素
	struct node *lchild;	//指向左孩子结点
	struct node *rchild;	//指向右孩子结点
} BTNode;
void CreateBTree(BTNode * &b,char *str)	//创建二叉树
{
	BTNode *St[MaxSize],*p;//St数组作为顺序栈
	int top=-1,k,j=0;//top为栈顶指针
	char ch;
	b=NULL;
	ch=str[j];
	while(ch!='\0')
    {
        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(b==NULL)
                b=p;
            else{
                switch(k)
            {
                case 1:St[top]->lchild=p;break;
                case 2:St[top]->rchild=p;break;
            }
        }
    }
    j++;
    ch=str[j];
}
}
void DestroyBTree(BTNode *&b)	//销毁二叉树
{	if (b!=NULL)
	{	DestroyBTree(b->lchild);
		DestroyBTree(b->rchild);
		free(b);
	}
}
BTNode *FindNode(BTNode *b,ElemType x) //查找值为x的结点
{
	BTNode *p;
	if (b==NULL)
		return NULL;
	else if (b->data==x)
		return b;
	else
	{
		p=FindNode(b->lchild,x);
		if (p!=NULL)
			return p;
		else
			return FindNode(b->rchild,x);
	}
}
BTNode *LchildNode(BTNode *p)
{
    return p->lchild;
}
BTNode *RchildNode(BTNode *p)
{
    return p->rchild;
}
int BTHeight(BTNode *b)		//求二叉树b的高度
{
int lchild,rchild;
if(b==NULL) return 0;
else
{
    lchild=BTHeight(b->lchild);
     rchild=BTHeight(b->rchild);
     return (lchild>rchild)?(lchild+1):(rchild+1);
}
}
void DispBTree(BTNode *b)  //以括号表示法输出二叉树
{
	if (b!=NULL)
	{	printf("%c",b->data);
		if (b->lchild!=NULL || b->rchild!=NULL)
		{	printf("(");						//有孩子结点时才输出(
			DispBTree(b->lchild);				//递归处理左子树
			if (b->rchild!=NULL) printf(",");	//有右孩子结点时才输出,
			DispBTree(b->rchild);				//递归处理右子树
			printf(")");						//有孩子结点时才输出)
		}
	}
}
int main()
{	BTNode *b,*p,*lp,*rp;;
	printf("二叉树的基本运算如下:\n");
	printf("  (1)创建二叉树\n");
	CreateBTree(b,"A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))");
	printf("  (2)输出二叉树:");DispBTree(b);printf("\n");
	printf("  (3)H结点:");
	p=FindNode(b,'H');
	if (p!=NULL)
	{	lp=LchildNode(p);
		if (lp!=NULL)
			printf("左孩子为%c ",lp->data);
		else
			printf("无左孩子 ");
		rp=RchildNode(p);
		if (rp!=NULL)
			printf("右孩子为%c",rp->data);
		else
			printf("无右孩子 ");
	}
	printf("\n");
	printf("  (4)二叉树b的高度:%d\n",BTHeight(b));
	printf("  (5)释放二叉树b\n");
	DestroyBTree(b);
	return 1;
}
2.代码如下:
#include <iostream>
#define MaxSize 100
using namespace std;
typedef char ElemType;
typedef struct node{
ElemType data;//数据元素
struct node *lchild;//指向左孩子结点
struct node *rchild;//指向右孩子结点
}BTNode;
typedef struct
{
    BTNode *data[MaxSize];//存放队中元素
    int front,rear;//队头和队尾指针
}SqQueue;//顺序队类型
void PreOrder(BTNode *b)//先序递归遍历
{
    if(b!=NULL)
    {
        printf("%c",b->data);
        PreOrder(b->lchild);
        PreOrder(b->rchild);
    }
}
void PreOrder1(BTNode *b)			//先序非递归遍历算法
{
	BTNode *St[MaxSize],*p;
    int top=-1;
    if (b!=NULL)
    {
        top++;						//根结点进栈
        St[top]=b;
        while (top>-1)				//栈不为空时循环
        {
            p=St[top];				//退栈并访问该结点
            top--;
            printf("%c ",p->data);
            if (p->rchild!=NULL)	//有右孩子,将其进栈
			{
               top++;
               St[top]=p->rchild;
			}
            if (p->lchild!=NULL)	//有左孩子,将其进栈
			{
               top++;
               St[top]=p->lchild;
			}
		}
		printf("\n");
	}
}
void InOrder(BTNode *b)//中序递归遍历
{
    if(b!=NULL)
    {
        InOrder(b->lchild);
        printf("%c",b->data);
         InOrder(b->rchild);
    }
}

void  InOrder1(BTNode *b)       //中序非递归遍历
{
BTNode *St[MaxSize];
	BTNode *p;
	int top=0;
  do{
    while(b)               //根指针t表示的为非空二叉树
    {
      St[top++]=b;             //根指针进栈
      b=b->lchild;           //t移向左子树
     }   //循环结束表示以栈顶元素的指向为根结点的二叉树
         
    if (top)                    //为非空栈
    { b=St[--top];             //弹出根指针
      printf("%c ",b->data);    //访问根结点
      b=b->rchild;             //遍历右子树
     }
   } while(top||b);//父结点未访问,或右子树未遍历
   printf("\n");
 }
void PostOrder(BTNode *b)//后序递归遍历
{
    if(b!=NULL)
    {
        PostOrder(b->lchild);
        PostOrder(b->rchild);
        printf("%c",b->data);
    }
}
void PostOrder1(BTNode *b)			//后序非递归遍历算法
{
	BTNode *St[MaxSize];
	BTNode *p;
	int top=-1;								//栈指针置初值
	bool flag;
	if (b!=NULL)
	{
		do
		{
			while (b!=NULL)					//将b结点的所有左下结点进栈
			{
				top++;
				St[top]=b;
				b=b->lchild;
			}
			p=NULL;							//p指向当前结点的前一个已访问的结点
			flag=true;						//flag为真表示正在处理栈顶结点
			while (top!=-1 && flag)
			{
				b=St[top];					//取出当前的栈顶元素
				if (b->rchild==p)			//右子树不存在或已被访问,访问之
				{
					printf("%c ",b->data);	//访问b结点
					top--;
					p=b;					//p指向则被访问的结点
				}
				else
				{
					b=b->rchild;			//b指向右子树
					flag=false;				//表示当前不是处理栈顶结点
				}
			}
		} while (top!=-1);
		printf("\n");
	}
}
void InitQueue(SqQueue *&q)
{
  q=(SqQueue*)malloc(sizeof(SqQueue));
  q->front=q->rear=-1;
}
void DestroyQueue(SqQueue *&q)//销毁队列
{
    free(q);
}
bool enQueue(SqQueue *&q,BTNode *e)		//进队列
{	if ((q->rear+1)%MaxSize==q->front)	//队满上溢出
		return false;
	q->rear=(q->rear+1)%MaxSize;
	q->data[q->rear]=e;
	return true;
}
bool deQueue(SqQueue *&q,BTNode *&e)	//出队列
{	if (q->front==q->rear)				//队空下溢出
		return false;
	q->front=(q->front+1)%MaxSize;
	e=q->data[q->front];
	return true;
}
bool QueueEmpty(SqQueue *q)//判断为空
{
    return (q->front==q->rear);
}
void LevelOrder(BTNode *b)
{
	BTNode *p;
	SqQueue *qu;
	InitQueue(qu);					//初始化队列
	enQueue(qu,b);					//根结点指针进入队列
	while (!QueueEmpty(qu))			//队不为空循环
	{
		deQueue(qu,p);				//出队节点p
		printf("%c ",p->data);		//访问节点p
		if (p->lchild!=NULL)		//有左孩子时将其进队
			enQueue(qu,p->lchild);
		if (p->rchild!=NULL)		//有右孩子时将其进队
			enQueue(qu,p->rchild);
	}
}
void CreateBTree(BTNode *&b,char *str)//创建二叉树
{
    BTNode *St[MaxSize],*p;
    int top=-1,k,j=0;
    char ch;
    b=NULL;
    ch=str[j];
    while(ch!='\0')
    {
        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(b==NULL)
                b=p;
            else
            {
                switch(k)
                {
                    case 1:St[top]->lchild=p;break;
                    case 2:St[top]->rchild=p;break;
                }
            }
        }
        j++;
        ch=str[j];
    }
}
void DestroyBTree(BTNode *&b)//销毁二叉树
{
    if(b!=NULL)
    {
      DestroyBTree (b->lchild);
      DestroyBTree(b->rchild);
      free(b);
    }
}
void DispBTree(BTNode *b)//输出二叉树
{
    if(b!=NULL)
    {
        printf("%c",b->data);
        if(b->lchild!=NULL||b->rchild!=NULL)
        {
            printf("(");
            DispBTree(b->lchild);
            if(b->rchild!=NULL)
                printf(",");
            DispBTree(b->rchild);
            printf(")");

        }
    }
}
int main()
{
    BTNode *b;
    CreateBTree(b,"A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))");
    printf("二叉树为:");
    DispBTree(b);
    printf("\n");
    printf("先序遍历序列:\n");
	printf("    递归算法:");
	PreOrder(b);printf("\n");
	printf("  非递归算法:");
	PreOrder1(b);
	printf("中序遍历序列:\n");
	printf("    递归算法:");
	InOrder(b);
	printf("\n");
	printf("  非递归算法:");
	InOrder1(b);
	printf("后序遍历序列:\n");
	printf("    递归算法:");
	PostOrder(b);
	printf("\n");
	printf("  非递归算法:");
	PostOrder1(b);
	printf("层次遍历序列:");
	LevelOrder(b);
	DestroyBTree(b);
    return 0;
}
3.代码如下:
#include <stdio.h>
#include <string.h>
#define N 50		//叶子结点数
#define M 2*N-1		//树中结点总数
typedef struct
{
	char data[5];	//结点值
   double weight;//权重
   int lchild;//左孩子
   int rchild;//右孩子
   int parent;//双亲结点
} HTNode;
typedef struct
{
	 char cd[N];		//存放哈夫曼码
	 int start;
} HCode;
void CreateHT(HTNode ht[],int n)  //由ht的叶子结点构造完整的哈夫曼树
{
	int i,k,lnode,rnode;
	double min1,min2;
	for(i=0;i<=2*n-1;i++)
        ht[i].parent=ht[i].lchild=ht[i].rchild=-1;
    for(i=n;i<=2*n-2;i++)
     {
           min1=min2=32767;
           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)	//由哈夫曼树ht构造哈夫曼编码hcd
{
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++;
    hcd[i]=hc;
}
}
void DispHCode(HTNode ht[],HCode hcd[],int n)	//输出哈夫曼编码
{
	int i,k;
	int sum=0,m=0,j;
	printf("输出哈夫曼编码:\n");
	for (i=0;i<n;i++)
	{
		j=0;
		printf("          %s:\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("平均长度=%g\n",1.0*sum/m);
}
int main()
{
	int n=15,i;
	char *str[]={"The","of","a","to","and","in","that","he","is","at","on","for","His","are","be"};//定义单词字符数组
	double fnum[]={1192,677,541,518,462,450,242,195,190,181,174,157,138,124,123};//定义每个单词字符的使用频率数组
	HTNode ht[M];
	HCode hcd[N];
	for (i=0;i<n;i++)//完成n个叶子结点的初始化
	{
		strcpy(ht[i].data,str[i]);
		//ht[i].data=str[i];
		ht[i].weight=fnum[i];
	}
	CreateHT(ht,n);
	CreateHCode(ht,hcd,n);
	DispHCode(ht,hcd,n);
	return 1;
}

如有不足,请指教

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值