概念
??传统的使用二叉链表实现的二叉树由于会有n+1个空间没有使用上,因此我们可以在该二叉树上使用其没有使用的空指针域,让这些指针域指向该节点的前驱或后继节点,以实现空间最大利用率,同时这种新的二叉树在需要知道某个之间的前驱或后继节点也更加的方便自如,那么这种二叉树就叫做—线索二叉树,我们规定,如果某个节点的左孩子为空,则其左孩子的指针域改为指向其前驱节点,如若右孩子为空,那么右孩子的指针域指向该节点的后继节点。
实例
先对这棵树中序遍历,之后就可以知道每一个结点的前驱和后继节点了。 然后根据上面的规则我们就能得到一个新的二叉树。 当然,你可能会发现,如果这样子那么基本每一个节点的左右孩子都不是空的,那么我如何知道这个结点指向的到底是前驱还是后继指针还是我的孩子呢? 因此,我们需要在二叉树的每一个结点补上一个标志域Ltag和Rtag。 并且规定: ????Ltag=0代表的是左孩子 ????Ltag=1代表的是前驱结点 ????Rtag=0代表的是右孩子 ????Rtag=1代表的是后继结点
代码以及实现思想
以文件内的这棵树为例(可能字迹有点丑) 笔记,免积分下载
先输入如图的二叉树,以中序遍历的情况可以得到DBEAC 那么如何可以做到这种效果? 1:构建二叉树 首先输入一个要插入的每一个元素,如果其子树为空,则输入#结束 其数据分为左右标记位,指针域,数据域
typedef struct ThreadTreeNode {
char data;
struct ThreadTreeNode* lchild;
struct ThreadTreeNode* rchild;
int LTag;
int RTag;
}Tnode, * Ttree;
void CreateBinaryTree(Ttree& T)
{
char ch;
cin >> ch;
if (ch == '#')
{
T = NULL;
}
else
{
if (!(T = (Tnode*)malloc(sizeof(Tnode)))) exit(0);
T->data = ch;
T->LTag = Link;
T->RTag = Link;
CreateBinaryTree(T->lchild);
CreateBinaryTree(T->rchild);
}
}
2:中序遍历的方式线索化二叉树 先创建一个头节点Thrt,这个头节点用于指向二叉树的根节点 同时二叉树的最后一个结点的右孩子指向该头节点,形成一个闭环 首先令该头节点的右孩子指向自己(暂时),令左孩子指向二叉树的根节点 之后调用线索化函数void TheadBinaryTree(Ttree p),线索化该二叉树,线索化思想为先找到最左的结点,如果该最左的左孩子为空(最左自然为空),那么我们将其左孩子指向该节点的前驱结点(如果这个结点本身就是第一个结点,那么让他指向头结点),之后右结点也通过递归的方法,传入当前结点§,pre结点此时指向的以及是前一个结点,那么之后只要pre的右结点令其指向当前传入的结点§,那么就可以将前一个访问的结点的右孩子设置为其后驱结点,如此往复,线索化成功
void InOrderTheadBTree(Ttree& Thrt, Ttree T)
{
if (!((Thrt) = (Ttree)malloc(sizeof(Tnode))))
{
exit(0);
}
Thrt->LTag = Link;
Thrt->RTag = Thead;
Thrt->rchild = Thrt;
if (!T)
{
Thrt->lchild = Thrt;
}
else
{
Thrt->lchild = T;
pre = Thrt;
TheadBinaryTree(T);
pre->rchild = Thrt;
pre->RTag = Thead;
Thrt->rchild = pre;
}
}
void TheadBinaryTree(Ttree p)
{
if (p)
{
TheadBinaryTree(p->lchild);
if (!p->lchild)
{
p->LTag = Thead;
p->lchild = pre;
}
if (!pre->rchild)
{
pre->RTag = Thead;
pre->rchild = p;
}
pre = p;
TheadBinaryTree(p->rchild);
}
}
3:中序遍历线索二叉树 类似于中序遍历,先将指针指向最左的结点,输出该节点之后通过访问右孩子的方式(因为右孩子一定是后继结点)就可以遍历整棵线索二叉树,比较好理解
void InOrderTraverse(Ttree Thrt)
{
Ttree p;
p = Thrt->lchild;
while (p != Thrt)
{
while (p->LTag == Link)
{
p = p->lchild;
}
cout << p->data;
while (p->RTag == Thead && p->rchild != Thrt)
{
p = p->rchild;
cout << p->data;
}
p = p->rchild;
}
}
4:源代码
#pragma once
#include<iostream>
#include <cstdio>
#include<cstdlib>
typedef int Status;
typedef int ElemType;
typedef char cElemType;
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define MAXSIZE 20
#define make (struct student*)malloc(sizeof(struct student));
using namespace std;
enum Tag{Link,Thead};
typedef struct ThreadTreeNode {
char data;
struct ThreadTreeNode* lchild;
struct ThreadTreeNode* rchild;
int LTag;
int RTag;
}Tnode, * Ttree;
Ttree pre;
void CreateBinaryTree(Ttree& T);
void InOrderTheadBTree(Ttree& Thrt, Ttree T);
void TheadBinaryTree(Ttree p);
void InOrderTraverse(Ttree Thrt);
void CreateBinaryTree(Ttree& T)
{
char ch;
cin >> ch;
if (ch == '#')
{
T = NULL;
}
else
{
if (!(T = (Tnode*)malloc(sizeof(Tnode)))) exit(0);
T->data = ch;
T->LTag = Link;
T->RTag = Link;
CreateBinaryTree(T->lchild);
CreateBinaryTree(T->rchild);
}
}
void InOrderTraverse(Ttree Thrt)
{
Ttree p;
p = Thrt->lchild;
while (p != Thrt)
{
while (p->LTag == Link)
{
p = p->lchild;
}
cout << p->data;
while (p->RTag == Thead && p->rchild != Thrt)
{
p = p->rchild;
cout << p->data;
}
p = p->rchild;
}
}
void InOrderTheadBTree(Ttree& Thrt, Ttree T)
{
if (!((Thrt) = (Ttree)malloc(sizeof(Tnode))))
{
exit(0);
}
Thrt->LTag = Link;
Thrt->RTag = Thead;
Thrt->rchild = Thrt;
if (!T)
{
Thrt->lchild = Thrt;
}
else
{
Thrt->lchild = T;
pre = Thrt;
TheadBinaryTree(T);
pre->rchild = Thrt;
pre->RTag = Thead;
Thrt->rchild = pre;
}
}
void TheadBinaryTree(Ttree p)
{
if (p)
{
TheadBinaryTree(p->lchild);
if (!p->lchild)
{
p->LTag = Thead;
p->lchild = pre;
}
if (!pre->rchild)
{
pre->RTag = Thead;
pre->rchild = p;
}
pre = p;
TheadBinaryTree(p->rchild);
}
}
int main()
{
Ttree Thrt,T;
CreateBinaryTree(T);
InOrderTheadBTree(Thrt, T);
InOrderTraverse(Thrt);
}
|