线索二叉树的应用
二叉树遍历算法的应用

二叉树遍历算法的应用二叉树是一种常用的数据结构,它由节点和节点之间的链接组成。
每个节点最多有两个子节点,分别称为左子节点和右子节点。
二叉树遍历算法是指按照一定的顺序访问二叉树中的所有节点,经典的二叉树遍历算法有前序遍历、中序遍历和后序遍历。
这些遍历算法在计算机科学中有广泛的应用。
一、前序遍历前序遍历算法的访问顺序是先访问根节点,然后依次访问左子树和右子树。
在实际应用中,前序遍历算法十分常见,具有以下几个应用:1.树的复制:如果需要复制一棵二叉树,可以使用前序遍历算法遍历原树,然后按照递归或迭代的方式创建新节点,并复制原节点的值。
2.表达式求值:对于一个二叉树表示的数学表达式,前序遍历算法可以用来计算表达式的值。
遍历到运算符节点时,先计算左子表达式的值,然后计算右子表达式的值,最后根据运算符进行计算。
3.文件系统遍历:文件系统可以被视为一个树状结构,前序遍历算法可以按照前序的顺序遍历文件系统中的所有文件和文件夹。
二、中序遍历中序遍历算法的访问顺序是先访问左子树,然后访问根节点,最后访问右子树。
中序遍历算法也有多个应用:1.二叉树的中序遍历得到的节点值是按照从小到大的顺序排列的。
因此,可以使用中序遍历算法验证一个二叉树是否为二叉树。
2.二叉树中序遍历的结果可以用来实现按照升序排列的有序集合的功能。
例如,在数据库中存储的数据可以通过中序遍历的结果进行排序。
3.中序遍历算法可以将一个二叉树转换为一个有序的双向链表。
在遍历过程中,维护一个前驱节点和一个后继节点,并进行链接操作。
三、后序遍历后序遍历算法的访问顺序是先访问左子树,然后访问右子树,最后访问根节点。
后序遍历算法也有多个应用:1.后序遍历算法可以用来计算二叉树的深度。
在遍历过程中,可以维护一个全局变量来记录最大深度。
2.后序遍历算法可以用来判断一个二叉树是否为平衡二叉树。
在遍历过程中,可以比较左右子树的高度差,判断是否满足平衡二叉树的定义。
3.后序遍历算法可以用来释放二叉树的内存。
先序线索化转圈问题

先序线索化转圈问题先序线索化转圈问题是一种经典的数学问题,它可以帮助我们探索数学中的先序遍历、线索化和环的概念。
让我们来了解一下先序遍历和线索化的含义。
我们将研究如何将这些概念应用到转圈问题上,并通过一些具体的例子来进一步理解。
1. 先序遍历在二叉树中,先序遍历是指先访问根节点,然后遍历左子树,最后遍历右子树。
这个遍历顺序可以用一个节点序列来表示,我们可以把先序遍历的结果存储在一个数组中。
在这个数组中,根节点的位置总是在左子树和右子树之前。
2. 线索化线索化是将二叉树中的空指针调整为指向前驱节点或后继节点的方式。
通过线索化,我们可以用指针在树中前进而不需要使用递归或栈。
对于一个二叉树的节点,如果它没有左子树,我们可以把它的左指针指向它的前驱节点;如果它没有右子树,我们可以把它的右指针指向它的后继节点。
3. 先序线索化转圈问题现在让我们来考虑一个有趣的问题:如何将一棵已经线索化的二叉树转化为一个环形链表呢?我们需要把每一个节点的右指针指向它的后继节点,并使得最后一个节点的后继节点指向第一个节点。
为了解决这个问题,我们可以使用先序遍历的思想。
我们可以从根节点开始,依次遍历每个节点,并将它的右指针指向它的后继节点。
我们还需要记录前一个访问的节点,以便将它的后继节点指向当前节点。
具体的步骤如下:- 如果当前节点为根节点,将它的右指针指向它的后继节点,并记录当前节点为前一个节点。
- 如果当前节点有左子树,递归处理左子树。
- 如果当前节点有右子树,继续遍历它的右子树。
通过这种方式,我们可以将一个已经线索化的二叉树转化为一个环形链表。
这个环形链表可以让我们在任意节点中,通过右指针循环遍历所有节点。
在实际应用中,先序线索化转圈问题可以用于优化二叉树的遍历算法。
由于线索化的特性,我们可以避免使用递归或栈,从而提高遍历的效率。
通过对先序线索化转圈问题的深入研究,我们可以更好地理解先序遍历、线索化和环的概念。
这个问题不仅提供了一个数学的挑战,还具有一定的实际应用价值。
二叉树的储存结构的实现及应用

二叉树的储存结构的实现及应用二叉树是一种常见的数据结构,它在计算机科学和算法设计中广泛应用。
二叉树的储存结构有多种实现方式,包括顺序储存结构和链式储存结构。
本文将从这两种储存结构的实现和应用角度进行详细介绍,以便读者更好地理解二叉树的储存结构及其在实际应用中的作用。
一、顺序储存结构的实现及应用顺序储存结构是将二叉树的节点按照从上到下、从左到右的顺序依次存储在一维数组中。
通常采用数组来实现顺序储存结构,数组的下标和节点的位置之间存在一定的对应关系,通过数学计算可以快速找到节点的父节点、左孩子和右孩子。
顺序储存结构的实现相对简单,利用数组的特性可以迅速随机访问节点,适用于完全二叉树。
1.1 实现过程在采用顺序储存结构的实现中,需要首先确定二叉树的深度,然后根据深度确定数组的长度。
通过数学计算可以得到节点间的位置关系,初始化数组并按照规定的顺序将二叉树节点逐一填入数组中。
在访问二叉树节点时,可以通过计算得到节点的父节点和子节点的位置,从而实现随机访问。
1.2 应用场景顺序储存结构适用于完全二叉树的储存和遍历,常见的应用场景包括二叉堆和哈夫曼树。
二叉堆是一种特殊的二叉树,顺序储存结构可以方便地实现它的插入、删除和调整操作,因此在堆排序、优先队列等算法中得到广泛应用。
哈夫曼树则是数据压缩领域的重要应用,通过顺序储存结构可以有效地构建和处理哈夫曼树,实现压缩编码和解码操作。
二、链式储存结构的实现及应用链式储存结构是通过指针将二叉树的节点连接起来,形成一个类似链表的结构。
每个节点包含数据域和指针域,指针域指向节点的左右孩子节点。
链式储存结构的实现相对灵活,适用于任意形态的二叉树,但需要额外的指针空间来存储节点的地址信息。
2.1 实现过程在链式储存结构的实现中,每个节点需要定义为一个包含数据域和指针域的结构体或类。
通过指针来连接各个节点,形成一个二叉树的结构。
在树的遍历和操作中,可以通过指针的操作来实现节点的访问和处理,具有较高的灵活性和可扩展性。
二叉树的5种基本形态。 -回复

二叉树的5种基本形态。
-回复二叉树是计算机科学中常用的数据结构之一,它由一个根节点和两个子节点组成,每个节点最多有两个子节点。
在这篇文章中,我们将探讨二叉树的五种基本形态。
一、满二叉树(full binary tree):满二叉树是一种特殊的二叉树,其中每个节点都有零个或两个子节点。
换句话说,满二叉树的每个内部节点都是一个分支节点。
满二叉树的特征是每一层的节点数量都是满的,最底层的节点与高度呈指数关系。
例如,一个满二叉树的高度为3,那么它有7个节点。
满二叉树的特点使得它在存储和搜索方面具有很高的效率。
然而,满二叉树的缺点是它需要较多的存储空间,并且在删除和插入节点时可能需要进行大量的重新排序。
二、完全二叉树(complete binary tree):完全二叉树是一种二叉树,其中除了最后一层外,每一层的节点都是满的,并且最后一层的节点从左到右连续排列。
换句话说,完全二叉树是一颗填满节点的树,只有最后一层的节点位置可以是不完全的,但是它们仍然从左到右排列。
完全二叉树的特点是它可以使用数组来表示,这样节省了存储空间。
此外,在完全二叉树中,插入和删除节点的操作也非常高效。
但是,相对于满二叉树,完全二叉树的节点数可能较少,并且在搜索方面的效率稍低。
三、平衡二叉树(balanced binary tree):平衡二叉树是一种特殊的二叉树,其中每个节点的左子树和右子树高度之差不超过1。
换句话说,平衡二叉树的高度在对数范围内增长。
平衡二叉树的特点是它保持了二叉搜索树的有序性,并且在插入和删除操作时能够自动调整以保持平衡。
这使得在平衡二叉树中搜索和插入节点时的时间复杂度保持在O(log n)级别。
但是,这种平衡性的维护也增加了操作的复杂性和内存需求。
四、搜索二叉树(binary search tree):搜索二叉树,也称为二叉查找树,是一种有序的二叉树。
在搜索二叉树中,所有左子树的值都小于父节点的值,而所有右子树的值都大于父节点的值。
二叉树前驱后继的查找

线索二叉树的运算1.查找某结点*p在指定次序下的前趋和后继结点(1)在中序线索二叉树中,查找结点*p的中序后继结点在中序线索二叉树中,查找结点*p的中序后继结点分两种情形:①若*p的右子树空(即p->rtag为Thread),则p->rchild为右线索,直接指向*p的中序后继。
【例】下图的中序线索二叉树中,结点D的中序后继是A。
②若*p的右子树非空(即p->rtag为Link),则*p的中序后继必是其右子树中第一个中序遍历到的结点。
也就是从*p的右孩子开始,沿该孩子的左链往下查找,直至找到一个没有左孩子的结点为止,该结点是*p的右子树中"最左下"的结点,即*P的中序后继结点。
【例】上图的中序线索二叉树中:A的中序后继是F,它有右孩子;F的中序后继是H,它无右孩子;B的中序后继是D,它是B的右孩子。
在中序线索二叉树中求中序后继结点的过程可【参见动画演示】,具体算法如下:BinThrNode *InorderSuccessor(BinThrNode *p){//在中序线索树中找结点*p的中序后继,设p非空BinThrNode *q;if (p->rtag==Thread) //*p的右子树为空Return p->rchild;//返回右线索所指的中序后继else{q=p->rchild;//从*p的右孩子开始查找while (q->ltag==Link)q=q->lchild;//左子树非空时,沿左链往下查找return q;//当q的左子树为空时,它就是最左下结点} //end if}该算法的时间复杂度不超过树的高度h,即O(h)。
(2)在中序线索二叉树中查找结点*p的中序前趋结点中序是一种对称序,故在中序线索二叉树中查找结点*p的中序前趋结点与找中序后继结点的方法完全对称。
具体情形如下:①若*p的左子树为空,则p->1child为左线索,直接指向*p的中序前趋结点;【例】上图所示的中序线索二叉树中,F结点的中序前趋结点是A②若*p的左子树非空,则从*p的左孩子出发,沿右指针链往下查找,直到找到一个没有右孩子的结点为止。
二叉树用途

二叉树用途二叉树是一种常用的数据结构,由节点和连接节点的边组成,其中每个节点最多有两个子节点,被称为左子节点和右子节点。
二叉树具有以下特点:1. 有层次结构:节点按照层次排列,每层从左到右。
2. 可以拥有零个、一个或两个子节点。
3. 二叉树的子树也是二叉树。
4. 深度为d的二叉树最多含有2^d-1个节点,其中d为二叉树的深度。
二叉树的用途非常广泛,下面将详细讨论几个主要的应用场景。
1. 搜索、排序和查找:二叉树可以用于快速搜索、排序和查找数据。
二叉搜索树是一种常用的二叉树类型,其中每个节点的值大于左子树的所有节点的值,小于右子树的所有节点的值。
通过二分查找算法,在二叉搜索树中可以快速定位目标值。
2. 堆:二叉堆是一种用于实现优先队列的数据结构。
它具有以下特点:任意节点的关键字值都小于(或大于)或等于其子节点的关键字值,根节点的关键字值最小(或最大);并且堆是一颗完全二叉树。
二叉堆的插入和删除操作的时间复杂度为O(log n),适用于一些需要高效的优先级操作的场景,例如任务调度。
3. 表达式树:二叉树可以用于存储和计算数学表达式。
表达式树是一种二叉树,其叶节点是操作数,内部节点是操作符。
通过遍历表达式树,我们可以通过递归的方式计算整个表达式的值。
4. 文件系统:二叉树可以用于组织和管理文件系统中的文件和文件夹。
每个节点代表一个文件或文件夹,左子节点代表文件夹下的子文件夹,右子节点代表同一层级下的其他文件或文件夹。
通过遍历二叉树,可以实现文件的查找、创建、删除等操作。
5. 数据压缩:哈夫曼树是一种常用的数据压缩算法,通过构建二叉树来实现。
在哈夫曼树中,出现频率较高的字符对应的节点位于树的较低层,而出现频率较低的字符对应的节点位于树的较高层。
通过对字符进行编码,并使用相对较短的编码表示高频字符,可以实现对数据的高效压缩和解压缩。
6. 平衡树:平衡树是一种特殊类型的二叉树,其左子树和右子树的高度差不超过1。
线索二叉树

遍历 线索 二叉 树非
{
while(p->ltag==0) p=p->left; /*从根往下找到"最左"的结
点,即中序序列的开始结点*/
do
{
递归 算法
printf("%c",p->date);/*访问结点*/
p=succ(p);
}while(p!=NULL); }
返回
}
树
数据结构
在中序遍历线索树过程中,按下述两条 原则即可找到后继结点:
– 1) 如果某结点的右线索标志域为1,说明其 右指针域是线索,这个线索所指的即是该结 点的后继结点;
– 2) 如果某结点的右线索标志为0,则其右指 针域是指向右儿子结点的指针,由此结点的 右儿子结点起按左指针域指针逐结点向左查 找,一直找到左线索标志域为1的结点,即 是该结点的后继结点。
{
中
if(p!=NULL)
序
{ inthread(p->left,pre); /*左子树线索化*/
线
if(p->left==NULL)
索
/*若当前结点的左子树为空,则建立指 向其前趋结点的前趋线索*/
化
{
算
p->ltag=1;
法
p->left=pre; }
else
p->ltag=0树;
if (pre!=NULL && pre->right==NULL)
这种结点类型和相应结点的指针类型定义如 下:
typedef struct tnode {
ElemType data; int ltag,rtag; /*ltag和rtag只能取值为0或1*/ struct tnode *left,*right; }tbtree;
线索二叉树

0 A0 0 B1
0 C0
1 D0
1 E1
1F1
1 G1
(b) root
0
1
ห้องสมุดไป่ตู้
0 A0
0 B1
0 C0
0 A0
0 B1
0 C0
1 D0
1 E1
1F1
1 D0
1 E1
1F1
1 G1
1 G1
(c)
(d)
线索二叉树 b—中序 c—前序 d—后序
一旦建立了某种方式的线索二叉树后,用户程序就可以 像操作双向链表一样操作该线索二叉树。
if(tree->current == tree->root) tree->nextComplete = 1;
}
int EndOfNext(ThreadBiTree *tree) //判断是否已到中序线索二叉树的最后一个结点 { return tree->nextComplete; }
例8-3 编写一个程序,首先建立如图8-10(a)所示的不带头结点的二叉树, 然后中序线索化该二叉树,最后用循环结构输出该中序线索化二叉树各结 点的序列信息。
这种算法设计要求分别设计三个函数: First():定位在第一个结点位置; Next():移动到下一个结点位置; End():是否已经到最后下一个结点位置; 当然,还需要一个根据二叉树构造线索二叉树的函数。
typedef struct { ThreadBiNode *root;
ThreadBiNode *current; int nextComplete; }ThreadBiTree;
规定:当某结点的左指针为空时,令该指针指向按某种方法遍历二叉树时 得到的该结点的前驱结点;当某结点的右指针为空时,令该指针指向按某种 方法遍历二叉树时得到的该结点的后继结点。仅仅这样做会使我们不能区分 左指针指向的结点到底是左孩子结点还是前驱结点,右指针指向的结点到底 是右孩子结点还是后继结点。因此我们再在结点中增加两个线索标志位来区 分这两种情况。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程设计说明书(数据结构课程设计)专业:网络工程课程名称: 数据结构课程设计班级: 网络B11-1设计题目: 线索二叉树的应用设计时间: 2013-2-25 至2013-3-8评语:_____________________________________________________________________________________________________________________________________________________________________________________________________评阅成绩:____评阅教师:__一、问题描述与需求分析1、问题描述本实验的问题是建立一个线索二叉树,并实现线索二叉树的插入、删除、恢复线索等功能。
2、功能需求分析本程序要实现的功能是: 1. 线索二叉树的建立。
2.线索二叉树的插入。
3.线索二叉树的删除。
4.线索二叉树的恢复。
想要完成上面的功能,我们首先是要知道上面是线索二叉树。
我们可以从数据结构的书上找到答案,利用二叉链表的空指针域将空的左孩子指针域改为指向其前驱,空的右孩子指针域改为指向其后继。
这种改变指向的指针称为线索,加上了线索的二叉链表称为线索链表。
N个结点的二叉链表中含有n+1个空指针域。
利用二叉链表中的空指针域,存放指向结点的在某种遍历次序下的前驱和后继结点的指针,这种加上了线索的二叉链表称为线索链表。
相应的二叉树称为线线索二叉树。
根据线索二叉树性质的不同,线索二叉树可以分为前序线索二叉树,中序线索二叉树和后续线索二叉树三种,此次课程设计中使用的是中序线索二叉树。
二、概要设计1、总体设计思路首先就是要建立一个二叉树,然后再对二叉树进行线索化。
线索链表中的结点结构为:其中:线索二叉树及其存储结构如在线索树上进行遍历,只需先找到序列中的第一个结点,然后依次找结点后继为空时而止。
以上图为例子说明在线索树中查找结点的后继。
树中所有叶子的结点是线索,则右链域直接指示结点的后继,如结点b的后继为结点*。
树中所有非终端结点的右链均为指针,则无法由此得到后继的信息。
然而根据中序遍历的规律可知,结点的后继应是遍历其右子树时访问的第一个结点,即右子树最左下的结点。
列入在找结点*的后继时,首先沿右指针找到其右子树的根结点“—”,然后顺其左指针往下直至其左标志为1的结点,即为结点* 的后继,在图中是结点c。
反之,在中序结点中找结点前驱的规律是:若其左标志为“1”,则左链为线索,指示其前驱,否则遍历左子树时最后访问的一个结点(左子树最右下的结点)为其前驱。
程序流程图2、模块简介本程序有五个模块功能。
每个模块功能均实现特定的功能。
1.二叉树的建立:中序输入二叉树,为程序提供数据,输入的时候空域用@表示。
2.进行二叉树的线索化:按中序遍历顺序将二叉树线索化,只需要在遍历的过程中将二叉树的每个结点的空的左右孩子的指针域分别修改为指向其前驱和后继,若其左子树为空,则将其左孩子域线索化,使其左孩子指针lchild指向其后继,并且ltag 置1.3插入操作:输入要插入的结点信息,然后再查找要插入结点的位置,插入新结点。
4删除操作,确定要删除的结点,查找出要删除的结点,找到之后会显示ltag和rtag信息。
5输出线索二叉树,输出的线索二叉树为经过处理的二叉树。
三、详细设计1、数据结构设计程序采用线索链表做存储结构。
程序中有二叉树的建立,插入,删除,恢复线索,这些操作都是基于线索链表作的。
2、算法分析与实现二叉树的建立:建立一个二叉树,需要按照某种顺序依次输入二叉树中的结点,且该输入顺序必须隐含结点间的逻辑结构信息。
这种建立的方法,按全二叉树的层次顺序,一次输入结点信息建立二叉链表的过程。
以@表示空结点,以#表示输入结束的标志,。
一次输入结点信息,若其不是虚结点,则建立一个新结点。
若新结点是第一个结点,则令其为跟结点,否则将新结点作为孩子链接到它的父亲结点上。
在函数中设置一个队列,该队列是一个指针类型的数组,保存以输入的结点的地址。
使队列指针front指向当前与孩子建立链接的父亲结点,,队尾指针rear指向当前输入的结点。
若rear为偶数,则该结点为父结点的左孩子,若rear 为奇数,则为父结点的右孩子。
若父结点或孩子结点为虚结点,则无需链接,若父结点与其两个孩子结点链接完毕,则使front指向下一个等待链接的父结点。
算法实现:Bithptr *Q[maxsize]; //建队为指针类型Bithptr *CreatTree(){front=1;rear=0; //置空队if(ch!='@') //不是虚结点.则建立结点s=(Bithptr *)malloc(sizeof(Bithptr));s->data=ch;s->lchild=NULL;s->rchild=NULL;s->rtag=0;s->ltag=0;if(s!=NULL&&Q[front]!=NULL) //孩子和双亲结点都不是虚结点if(rear%2==0) Q[front]->lchild=s;else Q[front]->rchild=s;if(rear%2==1)front++; //结点*Q[front]的两个孩子处理完front+1线索化算法:线索过程需要按照一定的顺序进行,此次程序使用的是中序遍历,所以线索化也将使用中序线索化。
按照某种遍历顺序将二叉树线索化,只需在遍历的过程中将二叉树的每个结点空的左右孩子的指针分别修改为指向其前驱和后继。
若其左右树为空,则将其左孩子域线索化,使其左孩子指针lchild指向其后继,并且ltag为1.要实现线索化,就要知道结点*pre是*p的前驱,而*p是*pre的后继。
这样,当遍历到结点*p时,可以进行,若*P有空指针域,则将相应的标志为1,;若*p 的左线索标志已经建立(p->ltag==1),则可使其前驱线索化,令p->lchild=pre;若*pre的左线索标志已经建立(pre->rtag==1),则可使其后继线索化,令pre->rchild=p;算法实现;void PreThread(Bithptr *root){PreThread(p->lchild); //左子树线索化if(pre&&pre->rtag==1)pre->rchild=p; //前驱结点后继线索化if(p->lchild==NULL)p->ltag=1;p->lchild=pre;if(p->rchild==NULL) //后继结点前驱线索化p->rtag=1;pre=p;PreThread(p->rchild);}}插入结点函数:在书中插入一个结点,必须要以固定的规则来进行插入。
本程序中树的输出使用了中序输出的方法,所以插入的时候使用的规则就是以中序输出为顺序,先查找到一个点,再将要插入的结点,作为该结点的前驱插入树中。
如中序为:→d→b→e→a→f→c→g。
插入的结点为:b,则插入后的顺序为→d→w→b→e→a →f→c→g。
使用查找孩子指针函数来查找结点位置的指针。
在查找的过程中要处理好线索指针和孩子指针的关系,不能将线索也当做孩子来处理了。
并且在循环的判断中,且不能使用以前的空位结束语句,而是要用标志域来进行判断。
在查找的过程中,考虑到树的递归性质,所以讲查找函数也设置成递归函数。
算法实现:Bithptr*SearchChild(Bithptr*point,char findnode){Bithptr *point1,*point2;if(point!=NULL){if(point->data==findnode)return point; //找到结点的信息.返回指针elseif(point->ltag!=1) { // 判断是否有左子树point1=SearchChild(point->lchild,findnode);//递归if(point1!=NULL)return point1;}if(point->rtag!=1){ //判断是否有右子树point2=SearchChild(point->rchild,findnode);//递归if(point2!=NULL)return point2;}return NULL;}elsereturn NULL;}在一棵树种插入一个结点,因为插入的位置不同,就对应着不同的插入情况。
当插入结点有左孩子时:找到左孩子的最右下结点将待插的结点插为其结点的右孩子。
当插入结点没有左孩子时:直接将带插的结点插为其结点的左孩子。
算法实现:结点有左子树时.p2=child;child=child->lchild;while(child->rchild&&child->rtag==0) //左子树的最右下结点child=child->rchild;p1->rchild=child->rchild; //后继线索化p1->rtag=1;child->rtag=0;child->rchild=p1; //连接结点p1->lchild=child; //前驱线索化p1->ltag=1;结点没左孩子的时.p1->lchild=child->lchild; //前驱化child->ltag=0;p1->ltag=1;child->lchild=p1;p1->rchild=childp1->rtag=1;删除结点函数:要在函数中删除一个结点,有几种不同的情况,在删除结点之前要先找到要删除的结点,调用查找孩子结点的函数Bithptr *SearchChild(Bithptr*point,char findnode),找到其结点指针的指针。
删除过程中设计的指针变换需要父亲结点的指针,所以就调用查找父亲结点的函数Bithptr*SearchPre(Bithptr *point,Bithptr *child)来查找该结点的父亲结点的指针。
删除的过程中有不同的情况。
1当要删除结点为父亲的左孩子时若要删除结点没有左右孩子:则直接删除;若要删除结点有左孩子没有右孩子:则要删除结点的左孩子给父亲结点的左孩子;若要删除结点有右孩子没有左孩子:则将要删除结点的右孩子给父亲结点的左孩子;若要删除结点左右孩子都有:将要删除结点的左子树的右子树接到孩子结点的右子树的最左下结点的左子树.再将孩子结点的右子树接到孩子结点左子树的右子树。