任务描述
本关任务:实现本实训所需头文件的基本函数。
相关知识
实验目的
掌握线索二叉树的有关知识;
掌握求解线索二叉树中结点前趋和后继的算法以及以相应次序遍历线索二叉树的算法;
掌握二叉树的线索化算法的设计。
线索二叉树是为了快速求解二叉树中结点在指定次序下的前驱和后继,而将二叉链表中空的左右孩子指针分别改为指向其前驱和后继结点而得到的结构,反映了运算对数据结构的设计的影响。因此,首先要了解线索二叉树的结构特点,其中原本为空的指针被修改为前驱和后继指针,使得对左右子树和线索的判断发生了变化。利用线索可以实现某些次序下的前驱和后继。本实验期望能理解线索二叉树的结构特点,实现各前驱和后接算法的求解,并掌握将二叉树转换为线索二叉树的算法,即线索化算法。
实验任务
说明:为使实验程序简洁直观,下面的部分实验程序中的一些功能实现仍以调用库函数程序”btrechar.h”中的函数的形式给出,并假设该库函数中定义了线索二叉树的相关功能,如显示线索二叉树等。
实验说明
线索二叉树的存储结构
线索二叉树的存储:线索二叉树仍采用二叉链表结构存储,其说明与上一实验中的说明类似,所不同的是,各结点中增加了区分孩子指针和线索的两个字段ltag和rtag,其含义如下:
ltag=0:表示所在结点中的lchild指示其左孩子
ltag=1:表示所在结点中的lchild指示其前趋(即为线索)
rtag=0:表示所在结点中的rchild指示其右孩子
rtag=1:表示所在结点中的rchild指示其后继(即为线索)
二叉链表中的指针类型还是定为bitre,结点类型为bnode,类型描述如下:
typedef struct bnode
{ char data; // 数据字段
struct bnode *lchild,*rchild; // 左右孩子指针
int ltag,rtag; // 左右线索标志
};
typedef bnode *bitre;
扩展二叉树
将所要建的二叉树中每个结点的空指针处再引出一个“孩子”结点,其值为一特定的值以标识其为空。例如,如果二叉树的结点值为字符型,则可以“.” 标识其为空,如图1和图2所示。称这样处理后的二叉树为原二叉树的扩展二叉树。扩展二叉树的先序或后序序列以及层次序列能唯一确定其原二叉树, 处理时只要将“.”作为空二叉树即可。
下面讨论采用扩展二叉树的先须序列输入构建二叉树的方法。例如,为构造图1 所示二叉树,则输入序列为ABD…E…CF…G…。
图1
图1 原二叉树
图1
图2 扩展二叉树
编程要求
在本关卡中,需要实现头文件”btrechar.h”的一些基本函数,各个函数的功能与参数说明如下:
函数: void load_bitre(bitre & t); 功能: 在函数内读取拓展二叉树的先序遍历序列构建原二叉树; 返回值: 通过引用返回。
函数: void display_bitre(bitre & root); 功能: 输出二叉树的先序遍历序列和中序遍历序列; 格式: PreOrder: xxxxxxx InOrder: xxxxxxx
函数: void display_thbitre(bitre & t); 功能: 先序遍历线索化二叉树,并输出依次遍历的结点信息; 格式: 每一行的格式为 data(i) ltag(i) lchild(i) rtag(i) rchild(i). 无孩子结点则 child(i) 为 ‘.’。
函数: void order_thread_bitre(bitre & t, bitre & pre); 功能: 先序线索化二叉树。
函数: void in_thread_bitre(bitre & t, bitre & pre); 功能: 中序线索化二叉树。
测试说明
输入数据:
拓展二叉树的先序遍历序列。
输出数据:
依次调用load_bitre, display_bitre, order_thread_bitre, display_thread_bitre函数。
开始你的任务吧,祝你成功!
# pragma once
#include<iostream>
#include <stdlib.h>
#include<cstdio>
#include<cstring>
using namespace std;
char *a=new char[100];
namespace exa{
struct bnode {
struct bnode * lchild, * rchild;
int ltag, rtag;
char data;
};
typedef bnode * bitre;
static bitre load_bitre(bitre &t)//我的创建二叉树function
{
char ch;
ch=getchar();
if(ch=='.')
{
t=NULL;
}
else
{
t=(bitre)malloc(sizeof(bnode));
t->data=ch;
t->ltag=t->rtag=0;
t->lchild=load_bitre(t->lchild);
t->rchild=load_bitre(t->rchild);
}
return t;
}
//输出二叉树的先序遍历序列和中序遍历序列;
//格式:
//PreOrder: xxxxxxx
//InOrder: xxxxxxx
/*void Preorder(bitre &root)
{
int static flag=0;
if(root)
{
if(flag==0)
{
cout<<"Preorder: ";
flag=1;
}
cout<<root->data;
Preorder(root->lchild);
Preorder(root->rchild);
}
}
void Inorder(bitre &root)
{
int static flag=0;
if(root)
{
if(flag==0)
{
cout<<"Inorder ";
flag=1;
}
Preorder(root->lchild);
cout<<root->data;
Preorder(root->rchild);
}
}
static void display_bitre(bitre &root)
{
Preorder(root);
cout<<endl;
Inorder(root);
cout<<endl;
}*/
void store(char ch,int i)
{
a[i]=ch;
}
static void PreOrder(bitre & root)
{
int static i=0;
if(root==NULL) {return;}
else {
cout << root->data;
store(root->data,i++);
PreOrder(root->lchild);
PreOrder(root->rchild);
}
}
static void InOrder(bitre & root)
{
if(root==NULL) {return;}
else {
InOrder(root->lchild);
cout << root->data;
InOrder(root->rchild);
}
}
static void display_bitre(bitre & root) {
cout<<"PreOrder: ";
PreOrder(root);
cout << '\n';
cout<<"InOrder: ";
InOrder(root);
cout << '\n';
}
void Print(bitre &t)
{
if(t->lchild!=NULL&&t->rchild!=NULL)
printf("%c %d %c %d %c\n",t->data,t->ltag,t->lchild->data,t->rtag,t->rchild->data);
else if(t->lchild!=NULL&&t->rchild==NULL)
printf("%c %d %c %d .\n",t->data,t->ltag,t->lchild->data,t->rtag);
else if(t->rchild!=NULL&&t->lchild==NULL)
printf("%c %d . %d %c\n",t->data,t->ltag,t->rtag,t->rchild->data);
else if(t->rchild==NULL&&t->lchild==NULL)
printf("%c %d . %d .\n",t->data,t->ltag,t->rtag);
}
//显示线索二叉树
//每一行的格式为 data(i) ltag(i) lchild(i) rtag(i) rchild(i)
//无孩子结点则 child(i) 为 '.'
void display_thread_bitre(bitre Root)
{
if (Root == NULL)
{
return;
}
bitre pCur = Root;
while (pCur != NULL)
{
while (pCur->lchild != NULL && pCur->ltag == 0)//找到最左边的节点,左标记一直为Link
{
Print(pCur);
pCur = pCur->lchild;
}
//到这来,左边的的节点还没有访问
Print(pCur);
if (pCur->ltag == 1)//遇到线索 就看右节点
{
pCur = pCur->rchild;
}
while (pCur != NULL)//循环右节点
{
if (pCur->lchild != NULL && pCur->ltag == 0)//遇到左节点存在 , 则访问
{
break;
}
Print(pCur);
pCur = pCur->rchild;
}
}
delete []a;
}
//先序线索化二叉树
static void order_thread_bitre(bitre & t, bitre & pre)
{
if(t==NULL)
{
return;
}
if(t->data==a[strlen(a)-1])
t->rtag=1;
if(t->lchild==NULL)
{
t->lchild = pre;
t->ltag = 1;
}
if(pre && pre->rchild==NULL)
{
pre->rchild = t;
pre -> rtag = 1;
}
pre = t;
if(t->ltag==0)
{
order_thread_bitre(t->lchild,pre);
}
if(t->rtag==0)
{
order_thread_bitre(t->rchild,pre);
}
}
}