《数据结构》算法设计题:假设二叉树采用二叉链存储结构,设计算法输出从根结点到每个叶子结点的路径逆序列。
要求二叉树从叶结点到根结点的路径,可以采用先序遍历、后序遍历、层次遍历等方法。本算法采用的是后序遍历非递归和先序遍历递归方法。把程序要用到的二叉树的基本运算写到文件btree.h里面,实现如下功能。
- CreateBtree(BTNode *&b, char *str):用二叉树括号串建立二叉链存储结构b。括号表示法形式:根(左子树,右子树)
- DispBTree(BTNode *b):以括号表示法输出二叉树
- DestroyBTree(BTNode *&b):销毁二叉树。
//文件名:btree.h
#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=NULL;
int top=-1,k,j=0;
char ch;
b=NULL; //建立的二叉树初始时为空
ch=str[j];
while (ch!='\0') //str未扫描完时循环
{
switch(ch)
{
case '(':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) //p指向二叉树的根节点
b=p;
else //已建立二叉树根节点
{
switch(k)
{
case 1:St[top]->lchild=p;break;
case 2:St[top]->rchild=p;break;
}
}
}
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(")");
}
}
}
#include "btree.h" //包含二叉树的基本运算算法
void PostOrder(BTNode *b) //后序遍历的递归算法
{
if (b!=NULL)
{
PostOrder(b->lchild); //递归访问左子树
PostOrder(b->rchild); //递归访问右子树
printf("%c ",b->data); //访问根节点
}
}
void PostOrder1(BTNode *b)
{ //后序遍历非递归算法
BTNode *St[MaxSize];
int top=-1; //栈指针置初值
BTNode *p=b;
BTNode *r=NULL;
while (p||top>-1)
{
if(p){
St[++top]=p;
p=p->lchild;
}
else
{
p=St[top]; //取出当前的栈顶元素
if (p->rchild &&p->rchild!=r) //右子树不存在或已被访问,访问之
{ p=p->rchild;
St[++top]=p;
p=p->lchild;
}
else //弹出节点并访问
{ printf("%c ",St[top]->data);
top--;
r=p; //r指向则被访问的节点
p=NULL;
}
}
}
}
void AllPath1(BTNode *b)
{ //后序遍历非递归算法输出每个叶子结点到根结点的路径序列
BTNode *St[MaxSize];
int top=-1; //栈指针置初值
BTNode *p=b;
BTNode *r=NULL;
while (p||top>-1)
{
if(p) //扫描结点p的所有左下结点并进栈
{ St[++top]=p; //结点p进栈
p=p->lchild; //移动到左孩子
}
else
{
p=St[top]; //取出当前的栈顶元素
if (p->rchild &&p->rchild!=r) //右子树不存在或已被访问,访问之
{ p=p->rchild;
St[++top]=p;
p=p->lchild;
}
else //弹出节点并访问
{ if (p->lchild==NULL && p->rchild==NULL) //若为叶子
{ //输出栈中所有结点值
for (int i=top;i>0;i--)
printf("%c->",St[i]->data);
printf("%c\n",St[0]->data);
}
top--;
r=p; //r指向则被访问的节点
p=NULL;
}
}
}
}
void Allpath2(BTNode *b,ElemType path[],int pathlen)
{ //先序遍历方法输出每个叶子结点到根结点的路径序列
if(b!=NULL)
{ if (b->lchild==NULL && b->rchild==NULL) //b为叶子
{ //输出栈中所有结点值
printf("%c->",b->data);
for (int i=pathlen-1;i>0;i--)
printf("%c->",path[i]);
printf("%c\n",path[0]);
}
else
{ path[pathlen++]=b->data;
Allpath2(b->lchild, path, pathlen);
Allpath2(b->rchild, path, pathlen);
}
}
}
void MaxPath(BTNode *b,ElemType path[],int pathlen,ElemType maxpath[],int &maxpathlen)
{ //先序遍历方法输出一条最长路径
if(b==NULL)//pathlen和maxpathlen的初值均为0
{ if(pathlen>maxpathlen) //通过比较求最长路径
{ for(int i=pathlen-1;i>=0;i--)
maxpath[i]=path[i];
maxpathlen=pathlen;
}
}
else
{ path[pathlen]=b->data; //将当前节点放入路径中
pathlen++; //路径长度增1
MaxPath(b->lchild,path,pathlen,maxpath,maxpathlen);
//递归扫描左子树
MaxPath(b->rchild,path,pathlen,maxpath,maxpathlen);
//递归扫描右子树
}
}
int main()
{
BTNode *b;
CreateBTree(b,"A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))");
printf("二叉树b:");DispBTree(b);printf("\n");
printf("后序遍历序列:\n");
printf(" 递归算法:");PostOrder(b);printf("\n");
printf(" 非递归算法:");PostOrder1(b);printf("\n");
printf("Allpath1:\n");AllPath1(b);printf("\n");
ElemType path[MaxSize],maxpath[MaxSize];
int maxpathlen =0;
printf("Allpath2:\n"); Allpath2(b,path,0);
printf("Maxpath:\n");
MaxPath(b,path,0,maxpath,maxpathlen);
for(int i=0;i<maxpathlen-1;i++)
printf("%c->",maxpath[i]);
printf("%c\n",maxpath[maxpathlen-1]);
DestroyBTree(b);
}
执行结果: