码迷,mamicode.com
首页 > 其他好文 > 详细

线索二叉树

时间:2016-08-08 07:42:21      阅读:276      评论:0      收藏:0      [点我收藏+]

标签:线索二叉树

1、什么是线索二叉树

        线索化的二叉树就是:在原有的二叉树基础上有些改动,将没有孩子结点的链域声明为线,左孩子指向前驱,右孩子指向后继节点;

有孩子结点的为链,表示指向原先的左右孩子;

线索二叉树的基本存储结构如下:

技术分享

2、中序二叉树的图形表示

技术分享

线索二叉树无需遍历,可以很方便的得到其任一结点的前驱、后继。+

3、中序线索二叉树的建立

        必须先建立好二叉树(根据先序序列),在其基础上创建中序线索二叉树;

核心程序:最好画图跟踪一下,才能弄得清楚;

注意:最后一个结点在函数结束时为LINK,没有更改过来!

template<typename Type>
void BinTree<Type>::createInThread(BinTreeNode<Type> *t, BinTreeNode<Type> *&pre){ //创建中序线索二叉树
    if(t == NULL){                        //pre必须引用传递,的保证及时的更改!!!
        return;  //空树直接返回
    }
    createInThread(t->leftChild, pre);  //pre一直为空,一直在往左走;
    if(t->leftChild == NULL){
        t->ltag = THREAD;  //将左孩子设置为线
        t->leftChild = pre;  //因为是第一个,无前驱,所以置空
    }
    if(pre != NULL && pre->rightChild == NULL){ 
        pre->rtag = THREAD;  //将右孩子设置为线;
        pre->rightChild = t;  //此时指向后继结点,t已经回到了上一层
    }
    pre = t;  //将当前结点给pre;
    createInThread(t->rightChild, pre); //往右边递归
}

完整创建程序:

#ifndef _THREAD_BIN_TREE_H_
#define _THREAD_BIN_TREE_H_

#include<iostream>
using namespace std;

typedef enum{LINK, THREAD}TAG;  //定义枚举标记链和线

template<typename Type>
class BinTree;

template<typename Type>  //结点类,多了两个标记链和线的;
class BinTreeNode{
    friend class BinTree<Type>;
public:
    BinTreeNode() : data(Type()), leftChild(NULL), rightChild(NULL), ltag(LINK), rtag(LINK){}
    BinTreeNode(Type value, BinTreeNode<Type> *left = NULL, BinTreeNode<Type> *right = NULL) :
    data(value), leftChild(left), rightChild(right), ltag(LINK), rtag(LINK){}
    ~BinTreeNode(){}
private:
    Type data;
    BinTreeNode *leftChild;
    BinTreeNode *rightChild;
    TAG            ltag;          //左标记
    TAG            rtag;         //右标记
};
///////////////////////////////////////////////////////////////////////////////
template<typename Type>
class BinTree{
public:
    BinTree() : root(NULL){}
    BinTree(Type ref) : root(NULL), refval(ref){}
    BinTree(const BinTree &t){}
    ~BinTree(){
    }
public:
    void createBinTree(const char *str);  //的先建立二叉树
    void createInThread();
protected :
    void createBinTree(const char *&str, BinTreeNode<Type> *&t);
    void createInThread(BinTreeNode<Type> *t, BinTreeNode<Type> *&pre);
template<typename Type>
void BinTree<Type>::createBinTree(const char *str){
    createBinTree(str, root);
}
template<typename Type>
void BinTree<Type>::createInThread(){  //在二叉树已经建立起来,创建中序线索二叉树;
    BinTreeNode<Type> *pre = NULL;  //得弄一个前驱节点,做为参数传递过去
    createInThread(root, pre);   //真正的创建中序线索二叉树
    pre->rtag = THREAD;  //最后一个应该为线
}
template<typename Type>
void BinTree<Type>::createInThread(BinTreeNode<Type> *t, BinTreeNode<Type> *&pre){ //创建中序线索二叉树
    if(t == NULL){
        return;
    }
    createInThread(t->leftChild, pre);
    if(t->leftChild == NULL){
        t->ltag = THREAD;
        t->leftChild = pre;
    }
    if(pre != NULL && pre->rightChild == NULL){
        pre->rtag = THREAD;
        pre->rightChild = t;
    }
    pre = t;
    createInThread(t->rightChild, pre);
}
template<typename Type>  //创建二叉树
void BinTree<Type>::createBinTree(const char *&str, BinTreeNode<Type> *&t){
    if(*str == refval){
        t = NULL;
    }else{
        t = new BinTreeNode<Type>(*str);
        createBinTree(++str, t->leftChild);
        createBinTree(++str, t->rightChild);
    }
}

#endif

4、其它方法的实现:

        中序线索二叉树

public:
    BinTreeNode<Type>* first()const;  //查找中序的第一个结点
    BinTreeNode<Type>* last()const;   //查找中序的最后一个结点
    BinTreeNode<Type>* prev(BinTreeNode<Type> *cur)const; //查找当前结点的前驱
    BinTreeNode<Type>* next(BinTreeNode<Type> *cur)const; //查找当前结点的后继
    BinTreeNode<Type>* parent(BinTreeNode<Type> *cur)const; //查找当前结点的父结点
    void inOrder()const;  //中序遍历线索二叉树
    BinTreeNode<Type>* find(const Type &key); //查找某一结点

        关于还有些方法: 求树高,求结点个数,这些其实跟前面写的差不多,将结束条件换为if(t->ltag == THREAD) return 0;

        (1)、查找第一个结点

template<typename Type>
BinTreeNode<Type>* BinTree<Type>::first(BinTreeNode<Type> *t)const{
    if(t == NULL){
        return NULL;
    }
    while(t->ltag == LINK){
        t = t->leftChild;
    }
    return t;
}

        (2)、查找最后一个结点

template<typename Type>
BinTreeNode<Type>* BinTree<Type>::last(BinTreeNode<Type> *t)const{
    if(t == NULL){
        return NULL;
    }
    while(t->rtag == LINK){
        t = t->rightChild;
    }

    return t;
}

        (3)、查找当前结点的前驱:

template<typename Type>
BinTreeNode<Type>* BinTree<Type>::prev(BinTreeNode<Type> *t, BinTreeNode<Type> *cur)const{
    if(t == NULL || cur == NULL){
        return NULL;
    }
    if(cur->ltag == THREAD){
        return cur->leftChild;
    }else{
        return last(cur->leftChild);  //当前结点的前驱是:左树的最后一个结点;
    }
}

        (4)、查找当前结点的后继

template<typename Type>
BinTreeNode<Type>* BinTree<Type>::next(BinTreeNode<Type> *t, BinTreeNode<Type> *cur)const{
    if(t == NULL || cur == NULL){
        return NULL;
    }
    if(cur->rtag == THREAD){
        return cur->rightChild;
    }else{
        return first(cur->rightChild);  //当前结点的后继是:右树的第一个结点;
    }   
}

        (5)、中序遍历线索化二叉树

template<typename Type>
void BinTree<Type>::inOrder(BinTreeNode<Type> *t)const{
    BinTreeNode<Type> *p;

    if(t == NULL){
        return;
    }
    for(p = first(t); p != NULL; p = next(t, p)){
        cout<<p->data<<" ";
    }
    cout<<endl;
}

        (6)、查找某一结点

template<typename Type>
BinTreeNode<Type>* BinTree<Type>::find(BinTreeNode<Type> *t, const Type &key){
    if(t == NULL){
        return NULL;
    }
    if(t->data == key){
        return t;
    }

    BinTreeNode<Type> *p;
    for(p = first(t); p != NULL; p = next(t, p)){
        if(p->data == key){
            return p;
        }
    }
    return NULL;
}

        (7) 、查找当前结点的父结点,分析如下:

1、为空,或当前为根结点,其父----->NULL
2、看看根是否为父结点;
3、就是图中E、D这种情况,其父----->后继结点
4、就是图中H、G这种情况,其父----->前驱结点
以上就是针对存在线的求法;
5、针对没有线的求法:(一)、例如求D:看的是其右的最后一个,因为线,走了一圈,就是确定B是其父;
(二)、找当前结点的左树的第一个,在返回其左孩子(此时这个线就是父节点);

template<typename Type>
BinTreeNode<Type>* BinTree<Type>::parent(BinTreeNode<Type> *t, BinTreeNode<Type> *cur)const{
    if(t == NULL || cur == NULL || cur == t){
        return NULL;   //父为空
    }
    if(t->ltag == LINK && t->leftChild == cur){  //父为根节点
        return t;
    } 
    if(t->rtag == LINK && t->rightChild == cur){
        return t;
    } 
    
    if(cur->rtag == THREAD && cur->rightChild->leftChild == cur){ //线的找
        return cur->rightChild;
    }
    if(cur->ltag == THREAD && cur->leftChild->rightChild == cur){  //线的找
        return cur->leftChild;
    }

    BinTreeNode<Type> *p = last(cur->rightChild);  //往右找最后一个,
    p = p->rightChild;
    if(p != NULL && p->leftChild->rightChild == cur){
        return p->leftChild;
    }
 
    p = first(cur->leftChild);  //换换思路,往左找第一个。
    return p->leftChild;
}

技术分享

5、完整代码、调试程序,测试结果

        (1)、代码

#ifndef _THREAD_BIN_TREE_H_
#define _THREAD_BIN_TREE_H_

#include<iostream>
using namespace std;

typedef enum{LINK, THREAD}TAG;

template<typename Type>
class BinTree;

template<typename Type>
class BinTreeNode{
    friend class BinTree<Type>;
public:
    BinTreeNode() : data(Type()), leftChild(NULL), rightChild(NULL), ltag(LINK), rtag(LINK){}
    BinTreeNode(Type value, BinTreeNode<Type> *left = NULL, BinTreeNode<Type> *right = NULL) :
    data(value), leftChild(left), rightChild(right), ltag(LINK), rtag(LINK){}
    ~BinTreeNode(){}
private:
    Type data;
    BinTreeNode *leftChild;
    BinTreeNode *rightChild;
    TAG            ltag;          //左标记
    TAG            rtag;         //右标记
};
///////////////////////////////////////////////////////////////////////////////
template<typename Type>
class BinTree{
public:
    BinTree() : root(NULL){}
    BinTree(Type ref) : root(NULL), refval(ref){}
    BinTree(const BinTree &t){}
    ~BinTree(){
    }
public:
    void createBinTree(const char *str);
    void createInThread();
public:
    BinTreeNode<Type>* first()const;
    BinTreeNode<Type>* last()const;
    BinTreeNode<Type>* prev(BinTreeNode<Type> *cur)const;
    BinTreeNode<Type>* next(BinTreeNode<Type> *cur)const;
    BinTreeNode<Type>* parent(BinTreeNode<Type> *cur)const;
    void inOrder()const;
    BinTreeNode<Type>* find(const Type &key);
protected:
    BinTreeNode<Type>* first(BinTreeNode<Type> *t)const;
    BinTreeNode<Type>* last(BinTreeNode<Type> *t)const;
    BinTreeNode<Type>* prev(BinTreeNode<Type> *t, BinTreeNode<Type> *cur)const;
    BinTreeNode<Type>* next(BinTreeNode<Type> *t, BinTreeNode<Type> *cur)const;
    BinTreeNode<Type>* parent(BinTreeNode<Type> *t, BinTreeNode<Type> *cur)const;
    void inOrder(BinTreeNode<Type> *t)const;
    BinTreeNode<Type>* find(BinTreeNode<Type> *t, const Type &key);
protected :
    void createBinTree(const char *&str, BinTreeNode<Type> *&t);
    void createInThread(BinTreeNode<Type> *t, BinTreeNode<Type> *&pre);
private:
    BinTreeNode<Type> *root;
    Type               refval;  //‘#‘
};
template<typename Type>
void BinTree<Type>::createBinTree(const char *str){
    createBinTree(str, root);
}
template<typename Type>
void BinTree<Type>::createInThread(){
    BinTreeNode<Type> *pre = NULL;
    createInThread(root, pre);
    pre->rtag = THREAD;  //最后一个应该为线
}
template<typename Type>
BinTreeNode<Type>* BinTree<Type>::first()const{
    return first(root);
}
template<typename Type>
BinTreeNode<Type>* BinTree<Type>::last()const{
    return last(root);
}
template<typename Type>
BinTreeNode<Type>* BinTree<Type>::prev(BinTreeNode<Type> *cur)const{
    return prev(root, cur);
}
template<typename Type>
BinTreeNode<Type>* BinTree<Type>::next(BinTreeNode<Type> *cur)const{
    return next(root, cur);
}
template<typename Type>
BinTreeNode<Type>* BinTree<Type>::parent(BinTreeNode<Type> *cur)const{
    return parent(root, cur);
}
template<typename Type>
void BinTree<Type>::inOrder()const{
    inOrder(root);
}
template<typename Type>
BinTreeNode<Type>* BinTree<Type>::find(const Type &key){
    return find(root, key);
}
//////////////////////////////////////////////////////////////////////////////////////////
template<typename Type>
BinTreeNode<Type>* BinTree<Type>::find(BinTreeNode<Type> *t, const Type &key){
    if(t == NULL){
        return NULL;
    }
    if(t->data == key){
        return t;
    }

    BinTreeNode<Type> *p;
    for(p = first(t); p != NULL; p = next(t, p)){
        if(p->data == key){
            return p;
        }
    }
    return NULL;
}
template<typename Type>
void BinTree<Type>::inOrder(BinTreeNode<Type> *t)const{
    BinTreeNode<Type> *p;

    if(t == NULL){
        return;
    }
    for(p = first(t); p != NULL; p = next(t, p)){
        cout<<p->data<<" ";
    }
    cout<<endl;
}
template<typename Type>
BinTreeNode<Type>* BinTree<Type>::parent(BinTreeNode<Type> *t, BinTreeNode<Type> *cur)const{
    if(t == NULL || cur == NULL || cur == t){
        return NULL;
    }
    if(t->ltag == LINK && t->leftChild == cur){
        return t;
    } 
    if(t->rtag == LINK && t->rightChild == cur){
        return t;
    } 
    
    if(cur->rtag == THREAD && cur->rightChild->leftChild == cur){
        return cur->rightChild;
    }
    if(cur->ltag == THREAD && cur->leftChild->rightChild == cur){
        return cur->leftChild;
    }

    BinTreeNode<Type> *p = last(cur->rightChild);
    p = p->rightChild;
    if(p != NULL && p->leftChild->rightChild == cur){
        return p->leftChild;
    }

    p = first(cur->leftChild);
    return p->leftChild;
}
template<typename Type>
BinTreeNode<Type>* BinTree<Type>::next(BinTreeNode<Type> *t, BinTreeNode<Type> *cur)const{
    if(t == NULL || cur == NULL){
        return NULL;
    }
    if(cur->rtag == THREAD){
        return cur->rightChild;
    }else{
        return first(cur->rightChild);
    }
    
}
template<typename Type>
BinTreeNode<Type>* BinTree<Type>::prev(BinTreeNode<Type> *t, BinTreeNode<Type> *cur)const{
    if(t == NULL || cur == NULL){
        return NULL;
    }
    if(cur->ltag == THREAD){
        return cur->leftChild;
    }else{
        return last(cur->leftChild);
    }
}
template<typename Type>
BinTreeNode<Type>* BinTree<Type>::last(BinTreeNode<Type> *t)const{
    if(t == NULL){
        return NULL;
    }
    while(t->rtag == LINK){
        t = t->rightChild;
    }

    return t;
}
template<typename Type>
BinTreeNode<Type>* BinTree<Type>::first(BinTreeNode<Type> *t)const{
    if(t == NULL){
        return NULL;
    }
    while(t->ltag == LINK){
        t = t->leftChild;
    }
    return t;
}
template<typename Type>
void BinTree<Type>::createInThread(BinTreeNode<Type> *t, BinTreeNode<Type> *&pre){
    if(t == NULL){
        return;
    }
    createInThread(t->leftChild, pre);
    if(t->leftChild == NULL){
        t->ltag = THREAD;
        t->leftChild = pre;
    }
    if(pre != NULL && pre->rightChild == NULL){
        pre->rtag = THREAD;
        pre->rightChild = t;
    }
    pre = t;
    createInThread(t->rightChild, pre);

}
template<typename Type>
void BinTree<Type>::createBinTree(const char *&str, BinTreeNode<Type> *&t){
    if(*str == refval){
        t = NULL;
    }else{
        t = new BinTreeNode<Type>(*str);
        createBinTree(++str, t->leftChild);
        createBinTree(++str, t->rightChild);
    }
}

#endif

        (2)、测试代码

#include"threadBinTree.h"

int main(void){
    char *str = "ABC##DE##F##G#H##";
    BinTree<char> bt(‘#‘);
    bt.createBinTree(str);
    bt.createInThread();

    bt.inOrder();
    BinTreeNode<char> *k = bt.find(‘A‘); //直接输入字符查找,其方法find(const Type &key)中的const万万不可少
    BinTreeNode<char> *p = bt.first();  //C
    printf("%p\n", k);  //A
    BinTreeNode<char> *m;
    m = bt.parent(p);   
//    printf("%p\n", m);  //B
    BinTreeNode<char> *n;
    n = bt.parent(m);
    printf("%p\n", n);  //A
    return 0;
}

        (3)、测试结果

技术分享



本文出自 “11586096” 博客,请务必保留此出处http://11596096.blog.51cto.com/11586096/1835476

线索二叉树

标签:线索二叉树

原文地址:http://11596096.blog.51cto.com/11586096/1835476

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!