目录
1.二叉树结构体定义
2.线索二叉树结构体定义
3.创建一个二叉树
4.遍历结点
5.中序化线索二叉树
6.在中序线索二叉树中找到p结点的后继
7.中序遍历中序线索二叉树
8.在中序线索二叉树中找到p结点的前驱
9.逆向遍历中序线索二叉树(这个出错了)
可以创建一个二叉树,然后将二叉树中序线索化,也可以直接创建一个中序线索二叉树,这里选择第一种方法
代码部分
//中序线索二叉树
#include<stdio.h>
#include<iostream>
using namespace std;
typedef char ElemType;
//1.二叉树结构体定义
typedef struct BiTNode {
ElemType data;
struct BiTNode* lchild, * rchild, * parent;//左孩子指针,右孩子指针,双亲指针
}BiTNode, * BiTree;
//2.线索二叉树结构体定义
typedef struct ThreadNode{
ElemType data;//数据域
struct ThreadNode* lchild, * rchild, * parent;//左、右孩子域,父节点指针
int ltag, rtag;//tag==0指向孩子,tag==1指向线索
}ThreadNode, *ThreadTree;
//全局变量pre,指向当前访问结点的前驱
ThreadNode* pre = NULL;
//3.创建线索二叉树
void CreateThreadTree_fill(ThreadTree& T) {
//例ABD##E##CF#G###
char ch;
cin >> ch;
if (ch == '#')
T = NULL;
else {
T = new ThreadNode; //生成根结点
T->data = ch;
T->ltag = 0;
T->rtag = 0;
T->parent = NULL;
CreateThreadTree_fill(T->lchild); //递归生成左子树
CreateThreadTree_fill(T->rchild); //递归生成右子树
}
}
//4.遍历结点
void Visit(ElemType x) {
cout << x << endl;;
}
void visit_root(ThreadNode* q) {
if (q->lchild == NULL) { //左子树为空,建立前驱线索
q->lchild = pre;
q->ltag = 1;
}
if (pre != NULL && pre->rchild == NULL) {
pre->rchild = q; //建立前驱结点的后继线索
pre->rtag = 1;
}
pre = q;
}
//中序线索化二叉树(中序遍历二叉树,一边遍历一边线索化)
void InThread(ThreadTree T) {
if (T != NULL) {
InThread(T->lchild);
visit_root(T);
InThread(T->rchild);
}
}
//(王道版教材)
//中序线索化
void InThread1(ThreadTree p, ThreadTree& pre) {
if (p != NULL) {
InThread1(p->lchild, pre);
if (p->lchild == NULL) {
p->lchild = pre;
p->ltag = 1;
}
if (pre != NULL && pre->rchild == NULL) {
pre->rchild = p;
pre->rtag = 1;
}
pre = p;
InThread1(p->rchild, pre);
}
}
//5.创建中序化线索二叉树
void CreateInThread(ThreadTree T) {
pre = NULL;
if (T != NULL) {
InThread(T);
//InThread1(T, pre);//王道版本
if (pre->rchild == NULL)
pre->rtag = 1;
}
}
//下面是找中序线索二叉树的后继和前驱
//一。在中序线索二叉树中找到指定结点*p的中序后继next
//1.若p->rtag==1,则next=p->lchild
//2.若p->rtag==0,则p必有右孩子, next为p的右子树中最左下结点
// 左 根(p) 右
// 左 根(p)(左 根 右)
// 左 根(p)((左 根 右) 根 右)
// next
//找到以p为根的子树中,第一个被中序遍历的结点(右子树中最左下结点)
ThreadNode* FirstNode(ThreadNode* p) {
//循环找到最左下结点
while (p->ltag == 0)
p = p->lchild;
return p;
}
//6.在中序线索二叉树中找到结点p的后继结点
ThreadNode* NextNode(ThreadNode* p) {
//右子树中最左下结点
if (p->rtag == 0)
return FirstNode(p->rchild);
else
return p->rchild; //rtag==1,直接返回后继线索
}
//7.对于中序线索二叉树进行中序遍历(利用线索实现的非递归算法)--王道版本
//空间复杂度O(1)
void InTraverse(ThreadNode* T) {
for (ThreadNode* p = FirstNode(T); p != NULL; p = NextNode(p))
Visit(p->data);
}
//中序线索二叉树进行中序遍历
void InTraverse_1(ThreadNode* T) {
ThreadNode* p = FirstNode(T);
while (p) {
Visit(p->data);
p = NextNode(p);
}
}
//二、中序线索二叉树找中序前驱
//在正序线索二叉树中找指定结点*p的中序前驱pre
//1.若p->ltag==1,则pre=p->lchild
//2.若p->ltag==0,则p必有左孩子,pre为左子树最右下结点
// 左 根(p) 右
// (左 根 右)根(p) 右
// (左 根 (左 根 右))根(p) 右
// pre
//找到以p为根的字数中,最后一个被中序遍历的结点(左子树最右下结点)
ThreadNode* LastNode(ThreadNode* p) {
//左子树的右下结点(不一定是叶子结点)
while (p->rtag == 0)
p = p->rchild;
return p;
}
//8.在中序线索二叉树中找到结点p的前驱结点
ThreadNode* PreNode(ThreadNode* p) {
if (p->ltag == 0)
return LastNode(p->lchild);
else
return p->lchild;//当ltag==1时,p的做线索即为前驱
}
//9.对中序线索二叉树进行逆向中序遍历
void RevTraverse(ThreadNode* T) {
for (ThreadNode* p = LastNode(T); p != NULL; p = PreNode(p))
Visit(p->data);
}
int main() {
ThreadTree T,inorder_nextnode, inorder_prenode;
//创建一颗二叉树 ABD##E##CF#G###
cout << "请输入一颗树:" << endl;
CreateThreadTree_fill(T);
//将二叉树中序线索化
InThread(T);
//在中序线索二叉树中找到指定结点*p的中序后继next
inorder_nextnode=NextNode(T->lchild);
if (inorder_nextnode != NULL)
cout << "该结点中序后继结点为:" << inorder_nextnode->data << endl;
else
cout << "该节点是没有后继结点" << endl;
//在中序线索二叉树中找到指定结点*p的中序前驱pre
//找B的前驱
inorder_prenode=PreNode(T->lchild);
if (inorder_prenode != NULL)
cout << "该结点中序前驱结点为:" << inorder_prenode->data << endl;
else
cout << "该结点为根结点,无前驱" << inorder_prenode->data << endl;
//对于中序线索二叉树进行中序遍历
cout << "对于中序线索二叉树进行中序遍历为:" << endl;
InTraverse_1(T);
//对于中序线索二叉树进行逆向中序遍历(失败)
//cout << "对于中序线索二叉树进行逆向中序遍历为:" << endl;
//RevTraverse(T);
}
运行部分
这里运行的树为ABD##E##CF#G###,选择的p结点为T->lchild,即B结点
该中序线索二叉树,中序遍历为DBEAFGC,
所以B结点的后继为E,前驱为D
图解部分
注:图解部分的树跟代码运行的树不是一颗树,图解是王道课的树的解析,解析包括中序线索二叉树找前驱和后继,前序线索二叉树找前驱和后继,后续线索二叉树找前驱和后继
1.前序线索二叉树找指定p结点的前驱和后继
2.前序线索二叉树找指定结点的前驱和后继
3.后序线索二叉树找指定结点的前驱和后继