二叉树构造方法

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

பைடு நூலகம்
R->data = ch;
Create(R->lch); Create(R->rch);
//创建左子树 //创建右子树
}
}
2)根据前序遍历序列和中序遍历序列构造二叉链表的二叉树
如图 5-2 所示的二叉树的前序序列和中序序列为:ABDEFCGH 和 DBFEAGHC,则如 何创建二叉链表的二叉树呢?
编程思路:
递归实现创建操作时用来表示的结点的类型为指针的引用*&,这是通过函数参数传 递来使用的,目的是将指针本身传递给函数;非递归实现过程中没有参数调用,无法使 用*&类型,因此使用 **来传递结点指针的地址。
c.以类前序序列做为输入进行实现。
程序代码:
template <class T>
void BiTree<T>::Create(BiNode<T>** R)
{ BiNode<T>** stack[MAXSIZE]; int top =-1;
//定义顺序栈 //栈顶指针
char ch;
do
{
cin>>ch;
while(ch!=’#’)
{ *R = new BiNode<T>;
//创建结点,保存根结点指针的地址
(*R)->data=ch;
(*R)->lch =(*R)->rch = NULL;
b.使用非递归的方法创建二叉树必须要注意输入的参数类型**;
首先,**是指针的指针,也就是**类型的变量存储的数据是一个指针的地址。举个 例子,已知 int a=5;则 int *p=&a; int **pp = &p;则变量 a、p、pp 的关系如图所示:
p a=5
pp p=&a
p 是一个指针变量,该变量存储的是变量 a 的地址;pp 就是一个指针的指针,该变 量存储的是指针 p 的地址。
所有创建二叉树的思路有其通用性,都是先创建根结点,再递归创建左子树和右子树, 那么本题就转化成如何查找根结点和左右子树的问题。
a. 如何找到二叉树的根呢?
这就需要在前序序列中找根结点,就是当前前序序列数组的首字符;
b. 如何找出这个根的左子树和右子树呢?
根据前序序列[1..n]中找出的根结点,查找在中序序列[1..n]中的位置 pos,则前序 序列中[2,pos]部分是左子树,[pos,n]部分就是右子树;
R->data = PreData[s1];
(*R)->lch =(*R)->rch = NULL;
int pos = find(InData,PreData[s1],s2,e2); //获取根结点在中序序列中的下标
Create(R->lch,PreData,InData, s1+1,s1+pos-s2,s2,pos-1); //创建左子树 Create(R->rch,PreData,InData, s1+pos-s2+1,e1,pos+1,e2); //创建右子树
程序代码:
使用模板类的形式实现该函数如下:
template <class T>
void BiTree<T>::Create(BiNode<T> *&R)
{
char ch;
cin>>ch; if (ch=='#')
//如果结点不存在
R = NULL;
else
{
R = new BiNode<T>;
//创建新的结点
stack[++top]= R;
//R入栈
R = &((*R)->lch);
//R指向当前结点的左孩子指针
cin>>ch;
} R = &((*stack[top])->rch); top--;
//R指向栈顶元素的右孩子指针 //栈顶元素出栈
}while((top!=-1)|| (a[i]!=0)); }
B D
A E
C G
F
H
9
图 5-2 示例二叉树
1)根据类前序序列构造二叉链表的二叉树
如 5-2 所示的二叉树可表示为如图 5-3 所示的扩展二叉树,即为每一个结点的空指针引 入一个虚结点“#”,该扩展二叉树的前序序列表示为:ABD##EF###CG#H###,其中结点 的顺序是前序序列,结点之间的“#”代表空结点。因此,从键盘输入该序列,可以唯一的 构造一个二叉树。
程序代码:
template <class T>
void BiTree<T>::Create(BiNode<T>*& R,T PreData[], T InData[],
int s1, int e1,int s2, int e2)
{
if (s1<=e1)
{ R = new BiNode<T>;
//创建根结点
3)使用非递归的方法创建二叉链表的二叉树 编程思路:
可以参考教材上前序遍历非递归实现的思路来编程。创建二叉树和前序遍历对每个结点 的访问顺序一致,因此二者程序结构基本相同,其区别有二点:一是是否创建新的结点,二 是是否需要将新结点的左右孩子指针传递到下一层;因此,在实现过程中注意以下 3 点就可。
a.非递归必须要使用栈来实现;
}
}
template <class T> int BiTree<T>::find(T InData[],T e,int s2,int e2) //寻找字符e在中序序列中的下标 {
for (int i=s2; i<=e2; i++) if (InData[i] == e) return i;
}
当然,第二种方法也可以使用后序序列和中序序列作为输入构造二叉树,其编程思想 和实现方法同上。请同学们自行编程实现。
二叉树构造方法
这里,给出另外两种常用的二叉树的创建方法,一是根据类前序序列作为输入构造二 叉链表的二叉树,二是根据前序遍历序列和中序遍历序列做为输入构造二叉链表的二叉树。 此外,二叉树的创建非常适合使用递归的方法来实现,逻辑简单易于实现;但是在非递归的 环境下也是可以实现的,实现逻辑较为复杂,因此也在本部分进行讨论。
A
B
C
D
E
#
#
F
#
9
9
#
#
9
G
#
9
#
H
9
#
#
9
编程思路:
图 5-3 扩展二叉树
根据创建二叉链表的思维方式,我们可以这么考虑该问题:若输入的是“#”如何处理? 若是结点字符,如何处理?显然当输入的是结点字符时,需要创建一个新结点,然后呢?递 归创建左子树,递归创建右子树。若输入的是“#”,则表明该二叉树为空树,即 R=NULL。
c. 递归创建 将[2,pos]看成是一棵二叉树,反复进行步骤 a 和 b;将[pos, n]看成是一棵二叉树,
反复进行步骤 a 和 b,直到该树为空结束。 d. 表示方法:
字符数组 PreData[]:表示前序序列 字符数组 InData[]:表示中序序列 s1 和 e1:表示当前处理的前序序列的起始和终止位置; s2 和 e2:表示当前处理的中序序列的起始和终止位置; find(InData,e,s2,e2):查找指定字符 e 在中序序列 InData 中的下标。
相关文档
最新文档