线索二叉树(中序)
声明:图片及内容基于https://www.bilibili.com/video/BV1kk4y1R777?from=articleDetail
原理
将树转化为线性链表,将遍历信息在首次便利时线索化,则可以在需要时直接获得结点的前驱后继,成为双向链表



具体定义和实现
节点结构

struct ThreadNode{
DataType data;
ThreadNode *lchild,*rchild;
int ltag,rtag;
};
中序线索二叉树结构

中序线索二叉树链表类的声明
class ThreadBiTree{
private:
TreadBiTree *root; //指向线索链表的头指针
public:
ThreadBiTree(); //构造函数,建立中序线索链表
~ThreadBiTree(); //析构函数,释放个结点的存储空间
ThreadNode* next(ThreadNode* p); //查找p的后继
void inOrder(); //中序遍历线索链表
private:
ThreadNode* create(ThreadNode* bt);
void inThread(TheadNode* p); //线索化二叉树
};
构造函数




中序遍历线索化模板

注意pre指针的定义

如果像上图那样定义,pre局部变量在每一次递归过程中都会重新定义为NULL

解决方法一:将pre定义为类的成员变量,在构造函数中初始化为NULL

解决方法二:将pre指针设置为静态变量

ThreadBiTree::ThreadBiTree(){
root=create(root);
inThread(root);
}
void ThreadBiTree::inThread(TheadNode* p){
static ThreadNode* pre=NULL;
if(p==NULL) return;
inThread(p->lchild);
if(p->lchild==NULL){ //针对p
p->ltag=1;
p->lchild=pre;
}
if(pre!=NULL&&pre->rchild==NULL){ //针对pre 注意pre!=NULL必须先判断,因为pre可能为NULL,这时pre->rchild没意义
pre->rchild=p;
pre->rtag=1;
}
pre=p;
inThread(p->rchild);
}
中序线索链表查找后继

ThreadNode* ThreadBiTree::next(ThreadNode* p) {
ThreadNode* q=NULL;
if (p->rtag == 1) {
q = p->rchild;
}
else {
q = p->rchild;
if (q == NULL) return NULL; //不写会报错,q可能为NULL
while (q->ltag == 0) {
q = q->lchild;
}
}
return q;
}
中序线索链表遍历算法
void ThreadBiTree::inOrder() {
ThreadNode* p;
if (root == NULL) return;
p = root;
while (p->ltag == 0) {
p = p->lchild;
}
cout << p->data << " ";
while (p->rchild != NULL) {
p = next(p);
cout << p->data << " ";
}
}
析构函数
ThreadBiTree::~ThreadBiTree() {
ThreadNode* p = root;
while (p->ltag == 0) {
p = p->lchild;
}
ThreadNode* q = p;
while (p) {
p = next(p); //利用next成员函数
delete q;
q = p;
}
}
完整代码
#include<iostream>
using namespace std;
struct ThreadNode {
char data;
ThreadNode* lchild=NULL, * rchild=NULL;
int ltag, rtag;
};
class ThreadBiTree {
private:
ThreadNode* root; //指向线索链表的头指针
public:
ThreadBiTree(); //构造函数,建立中序线索链表
~ThreadBiTree(); //析构函数,释放个结点的存储空间
ThreadNode* next(ThreadNode* p); //查找p的后继
void inOrder(); //中序遍历线索链表
private:
ThreadNode* create(ThreadNode* bt);
void inThread(ThreadNode* p); //线索化二叉树
};
ThreadNode* ThreadBiTree::create(ThreadNode* bt) {
char ch;
cin >> ch;
if (ch == '#') bt = NULL;
else {
bt = new ThreadNode;
bt->data = ch;
bt->ltag = 0;
bt->rtag = 0;
bt->lchild = create(bt->lchild);
bt->rchild = create(bt->rchild);
}return bt;
}
ThreadBiTree::ThreadBiTree() {
root = create(root);
inThread(root);
}
void ThreadBiTree::inThread(ThreadNode* p) {
static ThreadNode* pre = NULL;
if (p == NULL) return;
inThread(p->lchild);
if (p->lchild == NULL) {
p->ltag = 1;
p->lchild = pre;
}
if (pre != NULL && pre->rchild == NULL) {
pre->rchild = p;
pre->rtag = 1;
}
pre = p;
inThread(p->rchild);
}
ThreadNode* ThreadBiTree::next(ThreadNode* p) {
ThreadNode* q=NULL;
if (p->rtag == 1) {
q = p->rchild;
}
else {
q = p->rchild;
if (q == NULL) return NULL;
while (q->ltag == 0) {
q = q->lchild;
}
}
return q;
}
void ThreadBiTree::inOrder() {
ThreadNode* p;
if (root == NULL) return;
p = root;
while (p->ltag == 0) {
p = p->lchild;
}
cout << p->data << " ";
while (p->rchild != NULL) {
p = next(p);
cout << p->data << " ";
}
}
ThreadBiTree::~ThreadBiTree() {
ThreadNode* p = root;
while (p->ltag == 0) {
p = p->lchild;
}
ThreadNode* q = p;
while (p) {
p = next(p);
delete q;
q = p;
}
}
int main() {
ThreadBiTree tree;
tree.inOrder();
return 0;
}

浙公网安备 33010602011771号