1.二叉树的创建
定义二叉树的二叉链表存储形式:包括结点数据域,左右孩子指针,其中运用了递归操作
2.在二叉树中查找结点
3.二叉树的高度
如果是空树,递归结束,深度为0,否则执 行以下操作:
- 递归计算左子树的深度记为lsize;
- 递归计算右子树的深度记为rsize;
- 如果lsize>rsize,二叉树的深度为lsize+1,否则为rsize+1。
4.统计二叉树中结点个数
如果是空树,则结点个数为0;否则,结点个数为 左子树的结点个数加上右子树的结点个数
5. 二叉树的遍历
以前序遍历为例:
递归的出口:树为空:
否则,访问根结点,再调用自身遍历左子树及右子树;中序,后序,双序遍历的递归算法,在先序遍历的基础上改变访问根结点的顺序即可。
(1).树本身是一种非线性结构,在二叉树的基本操作的算法中多次利用到递归思想,二叉树本身的定义即为递归定义,调用自身定义左右孩子指针;后继的遍历等算法过程中也多次利用到递归;
(2).三种遍历算法的递归算法不同之处仅在于访问根结点和遍历左、右子树的先后关系,需要注意的是,任何一棵二叉树的叶子结点在先序,中序,后序遍历中,其访问的相对次序不变,包括双序遍历仅是在先序遍历的基础上,在访问右子树之前再次访问根结点;
(3).利用栈实现先序,中序遍历时,需要注意在定义栈的存储结构时,其头指针,尾指针的数据类型为指向根结点的指针的指针,队列实现层序遍历同理;
(4).本次实验是对之前所学栈,队列,递归的具体实现及综合应用,熟练掌握栈先进后出,队列先进先出的特性可以解决很多类似问题
//实验名:二叉树实验
#include <stdio.h>
#include <malloc.h>
#define MaxSize 100
typedef char ElemType;
typedef struct node
{
ElemType data; //数据元素
struct node *lchild; //指向左孩子
struct node *rchild; //指向右孩子
} BTNode;
//-------------------------------------------------------------------------------------------------------
//创建二叉树:由str串创建二叉树 例:L(I(U,S(H(I,L(I,M(,N))))),C(F,G(,I))) 字母从前到后替换为自己的姓名
//-------------------------------------------------------------------------------------------------------
void CreateBTNode(BTNode *&b, char *str)
{
BTNode *St[MaxSize], *p=NULL; //St数组作为顺序栈,保存双亲结点
int top = -1, k, j = 0; //top为栈顶指针
char ch;
b = 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指向它
p->data = ch; //存放结点值
p->lchild = p->rchild = NULL; //左右指针都设置为空
if (b == NULL) //尚未设置根结点
b = p; //p作为根结点
else
{
switch (k)
{
case 1:St[top]->lchild = p; break; //新建结点作为栈顶结点的左孩子
case 2:St[top]->rchild = p; break; //新建结点作为栈顶结点的右孩子
}
}
}
j++;
ch = str[j];
}
}
//-------------------------------------------------------------------------------------------------------
//查找结点:返回data域为x的结点指针
//-------------------------------------------------------------------------------------------------------
BTNode *FindNode(BTNode *b, ElemType 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);
}
}
//-------------------------------------------------------------------------------------------------------
//找左孩子结点:返回*p结点的左孩子结点指针
//-------------------------------------------------------------------------------------------------------
BTNode *LchildNode(BTNode *p) //返回结点p的左孩子指针
{
return p->lchild;
}
//-------------------------------------------------------------------------------------------------------
//找右孩子结点返回*p结点的右孩子结点指针
//-------------------------------------------------------------------------------------------------------
BTNode *RchildNode(BTNode *p) //返回结点p的右孩子指针
{
return p->rchild;
}
//-------------------------------------------------------------------------------------------------------
//求高度:求二叉树b的高度
//-------------------------------------------------------------------------------------------------------
int BTNodeDepth(BTNode *b)
{
int lchildh, rchildh;
if (b == NULL) return 0; //空树高度为0
else
{
lchildh = BTNodeDepth(b->lchild); //求左子树的高度
rchildh = BTNodeDepth(b->rchild); //求右子树的高度
return (lchildh > rchildh) ? (lchildh + 1) : (rchildh + 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(")");
}
}
}
//-------------------------------------------------------------------------------------------------------
//求二叉树b的结点个数
//-------------------------------------------------------------------------------------------------------
int Nodes(BTNode* b)
{
if (b == NULL)
{
return 0;
}
int lsize = Nodes(b->lchild);//统计左子树的节点个数
int rsize = Nodes(b->rchild); //统计右子树的节点个数
return 1 + lsize + rsize;
}
//-------------------------------------------------------------------------------------------------------
//销毁二叉树
//-------------------------------------------------------------------------------------------------------
void DestroyBTNode(BTNode *&b)//销毁一棵树
{
if (b != NULL)
{
DestroyBTNode(b->lchild);
DestroyBTNode(b->rchild);
free(b);
}
}
//-------------------------------------------------------------------------------------------------------
//先序遍历的递归算法
//-------------------------------------------------------------------------------------------------------
void PreOrder(BTNode *b)//先序遍历
{
if (b)
{
printf("%5c",b->data);//输出
PreOrder(b->lchild);//左子树
PreOrder(b->rchild);//右子树
}
}
//-------------------------------------------------------------------------------------------------------
//中序遍历的递归算法
//-------------------------------------------------------------------------------------------------------
void InOrder(BTNode *b)
{
if (b)
{
InOrder(b->lchild);//左子树
printf("%5c",b->data);
InOrder(b->rchild);//右子树
}
}
//-------------------------------------------------------------------------------------------------------
//后序遍历的递归算法
//-------------------------------------------------------------------------------------------------------
void PostOrder(BTNode *b)
{
if (b)
{
PostOrder(b->lchild);//左子树
PostOrder(b->rchild);//右子树
printf("%5c", b->data);
}
}
//-------------------------------------------------------------------------------------------------------
//以下是主函数
//-------------------------------------------------------------------------------------------------------
int main()
{
BTNode *b, *p, *lp, *rp;
//以括号法调用函数创建一颗二叉树
//L(I(U,S(H(I,L(I,M(,N))))),C(F,G(,I)))
char str[] = "L(I(U,S(H(I,L(I,M(,N))))),C(F,G(,I)))";
printf("二叉树的基本运算如下:\n");
CreateBTNode(b, str);//创建二叉树
printf("(1)输出二叉树:");
DispBTree(b);//输出二叉树
printf("\n");
printf("\n");
printf("(2)H结点:");//调用函数查找树中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("\n");
printf("(3)二叉树b的高度:");
printf("二叉树的高度为:%d\n",BTNodeDepth(b));//调用函数输出二叉树的高度
printf("\n");
printf("(4)二叉树b的结点个数: ");
printf("%d\n",Nodes(b));//调用函数输出二叉树的结点个数
printf("\n");
printf("(5)先序遍历序列:\n");
printf("递归算法:");
PreOrder(b);//调用函数对二叉树进行先序遍历
printf("\n");
printf("\n");
printf("(6)中序遍历序列:\n");
printf("递归算法:");
InOrder(b);//调用函数对二叉树进行中序遍历
printf("\n");
printf("\n");
printf("(7)后序遍历序列:\n");
printf("递归算法:");
PostOrder(b);//调用函数对二叉树进行后序遍历
printf("\n");
printf("\n");
printf("(8)销毁二叉树b\n");
DestroyBTNode(b);//调用函数销毁二叉树
printf("销毁成功\n");
return 0;
}