线索二叉树(中序)

声明:图片及内容基于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;
}

 

posted @ 2021-03-20 15:20  gonghr  阅读(1051)  评论(0)    收藏  举报