C++线索二叉树求最矮公共父亲节点

#include <iostream>
#include <stdlib.h>
#include <stack>
using namespace std;

class Expection//一个自定义的异常类
{
    public:
    void    Null_Thing()//空指针异常.
    {
        cout<<"Expection!!!,this is null"<<endl;
        exit (0);
    }
};

template<typename Type>
struct Node
{
    Type data;
    Node<Type> *left;
    Node<Type> *right;
    bool ltag;//线索我用bool类型存储。
    bool rtag;
    Node(Type d = Type()):data(d),left(NULL),right(NULL),ltag(false),rtag(false){}
};

template<typename Type>
class SBTree
{
    public:
    SBTree()
    {
        root = NULL;
    }
    void Insert(const char *s)
    {
            Insert(root,s);
    }
    void Printf()
    {
        Printf(root);
    }
    void Init_Thread()//二叉树的线索化。
    {
        Node<Type> *pre = NULL;
        _Init_Thread(root,pre);
    }
    Node<Type> *Fist()
    {
        return Fist(root);
    }
    void Init_SetDList()//构造双向链表,以root为头节点.
    {
        _Init_SetDList(root);
    }
    Node<Type> * Find(Type val)//寻找节点,找到则正常,如果找不到则抛出异常。
    {
        Node<Type> *p = NULL;
        try
        {
          p = Find(root,val);
        }
        catch(Expection exp)
        {
            exp.Null_Thing();
        }
        return p;
    }
    Type GetValue(Node<Type> *t)//将节点的Type值取出。
    {
        try
        {
        t = Find(t->data);
        }
        catch(Expection exp)
        {
            exp.Null_Thing();
        }
        return t->data;
    }
    Type GetCommParent(Type val1,Type val2)//得到两个节点的最矮公共父亲节点,这才是我想重点写的,其他的都是辅助,
    {
        if(_GetCommParent(root,val1,val2))
                            return _GetCommParent(root,val1,val2)->data;
    }
    private:
    Node<Type>* _GetCommParent(Node<Type> *t,Type val1,Type val2)
    {
        stack<Node<Type>* > st;
        if(Find_commparent(t,val1) && Find_commparent(t,val2))
        st.push(t);
        while(1)
        {
            if(Find_commparent(t->left,val1) && Find_commparent(t->left,val2))
                {
                t=t->left;
                st.push(t);
                }
            else if(Find_commparent(t->right,val1) && Find_commparent(t->right,val2))
                {
                t=t->right;
                st.push(t);
                }
            else
                {
                 if(st.empty()==false)
                    {
                    t = st.top();//用栈搞吧,好像与我开始的本意不符合。
                    st.pop();//悲剧的我没有用递归搞出来,想的我要吐了,思想是懂了,可是代码总是有问题,唉,容我三思。
                    return t;
                    }
                    else return NULL;
                }
        }
    }
    bool Find_commparent(Node<Type> *t,Type val)
    {
        if(t==NULL) return false;
        if(t->data == val)return true;
        else
        {
            bool BOOL = Find_commparent(t->left,val);
            if(BOOL==true)
                return true;
              BOOL =  Find_commparent(t->right,val);
            if(BOOL == true)
                return true;
        }
    }
    Node<Type>* Find(Node<Type> *t,Type val)
    {
        Node<Type> *p = NULL;
        try
        {
            p = First(t);
        }
        catch(Expection exp)
        {
            exp.Null_Thing();
        }
        while(p!=NULL)
        {
            if(p->data == val)break;
            p = p->right;
        }
        if(p!=NULL)return p;
        else throw Expection();
    }
    void _Init_SetDList(Node<Type> *t)
    {
            Node<Type> *p = NULL;
            try
            {
                p = First(t);
            }
            catch(Expection exp)
            {
                    exp.Null_Thing();
            }
            root = p;
            while(p!=NULL)
            {
                cout<<p->data<<" ";
                p = p->right;
            }
    }
    Node<Type> *First(Node<Type> *t)
    {
        if(t==NULL)throw Expection();
        else
        while(t->left!=NULL)
        {
            t = t->left;
        }
        return t;
    }
    bool _Init_Thread(Node<Type> *&t,Node<Type> *&pre)
    {
        if(t==NULL)
            {
            return true;
            }
        _Init_Thread(t->left,pre);

        if(pre != NULL && pre->right==NULL)
        {
            pre -> right = t;
            pre -> rtag = true;
        }

        if(t!=NULL && t->left==NULL)
        {
            t->left = pre;
            t->ltag = true;
        }
        pre = t;
        _Init_Thread(t->right,pre);
    }

    bool Insert(Node<Type> *&t,const char *&s)
    {
        if(*s==‘#‘)
        {
            t = NULL;
            return true;
        }
        else
        {
            t = new Node<Type>(*s);
            Insert(t->left,++s);
            Insert(t->right,++s);
        }
    }

    void Printf(Node<Type> *t)
    {
        if(t!=NULL)
        {
            cout<<t->data<<"\t";
            Printf(t->left);
            Printf(t->right);
        }
    }
    private:
    Node<Type> *root;
};
int main()
{
    char str[]="ABCD###EF##G##HI##J#K##";
    SBTree<char> sb;
    sb.Insert(str);
    //sb.Init_Thread();
    //sb.Find(‘2‘);
    cout<<sb.GetCommParent(‘C‘,‘D‘)<<endl;
    //sb.Init_SetDList();构造双向链表.
    //  sb.Printf();
    return 0;
}
时间: 2024-08-27 12:54:06

C++线索二叉树求最矮公共父亲节点的相关文章

二叉树中寻找共同节点的最低公共祖先节点

问题:在一棵二叉树中,给定两个节点,求这两个节点的最低的公共祖先节点,如下图中的,节点 6 和 节点 9 的最低公共祖先节点是节点 5. 最容易联想到的是,这个问题似乎与公共子串的问题有关系,如果我们能求出两个节点到根节点的路径,再使用匹配算法得到公共的路径,取这个路径上最后一个节点,即是所求的最低公共祖先节点. 哈夫曼编码启迪了我,我打算使用 0 表示向左走,1 表示向右走.如,101 表示自根节点,走到右孩子 A,再走到 A 的左孩子 B,再走到 B 的右孩子 C .于是,根节点到节点 C

线索二叉树的实现

<span style="font-size:18px;">/* 1.二叉树遍历算法提供了二叉树的一次性遍历,可是二叉树遍历算法无法实现用户程序像分步 遍历单链表那样分步遍历二叉树.线索二叉树就是专门为实现分步遍历二叉树而设计的.线索二叉树能够实现像双向 链表那样,既能够从前向后分步遍历二叉树,又能够从后向前分步遍历二叉树 2.当按某种规则遍历二叉树时,保存遍历时得到的节点的后继节点信息和前驱节点信息的最经常使用的方法是建立线索二叉树 3.线索二叉树的规定:当某节点的左指针

笔试算法题(41):线索二叉树(Threaded Binary Tree)

出题:线索二叉树(Threaded Binary Tree) 分析: 为除第一个节点外的每个节点添加一个指向其前驱节点的指针,为除最后一个节点外的每个节点添加一个指向其后续节点的指针,通过这些额外的指针可以某种遍历方式对二叉树进行遍历,而加了这些额外指针的二叉树就是线索二叉树: 对于含有N个节点的二叉树而言,一共有2N个指针,但除了根节点的其他节点都有来自其父节点的指针,所以耗用了N-1个指针,则最终剩下2N-(N- 1)=N+1个空指针:线索二叉树就是利用这些空指针存储具有某种遍历顺序的前驱和

二叉树最近公共父节点

在二叉树中找最近公共父节点.分为两种情况,一种是有父指针,一种没有父指针. 1.有父指针 这种情况比较简单,计算两个结点的深度,再把深度大的向上移,移到同一深度.在同时向上移动,直到两个结点相同,这样便找到了父节点.这个算法时间复杂度为O(N). 代码实现: #include<iostream> struct Node { int data; Node* left; Node* right; Node* parent; Node() :left(NULL), right(NULL), pare

一步两步学算法之中序遍历线索二叉树

1 typedef enum 2 { 3 SubTree, //子树 4 Thread //线索 5 }NodeFlag; 6 7 typedef struct ThreadTree 8 { 9 DATA data; 10 NodeFlag lflag; 11 NodeFlag rflag; 12 struct ThreadTree *left; 13 struct ThreadTree *right; 14 }ThreadBinTree; 15 16 ThreadBinTree *Previo

数据结构(三):非线性逻辑结构-特殊的二叉树结构:堆、哈夫曼树、二叉搜索树、平衡二叉搜索树、红黑树、线索二叉树

在上一篇数据结构的博文<数据结构(三):非线性逻辑结构-二叉树>中已经对二叉树的概念.遍历等基本的概念和操作进行了介绍.本篇博文主要介绍几个特殊的二叉树,堆.哈夫曼树.二叉搜索树.平衡二叉搜索树.红黑树.线索二叉树,它们在解决实际问题中有着非常重要的应用.本文主要从概念和一些基本操作上进行分类和总结. 一.概念总揽 (1) 堆 堆(heap order)是一种特殊的表,如果将它看做是一颗完全二叉树的层次序列,那么它具有如下的性质:每个节点的值都不大于其孩子的值,或每个节点的值都不小于其孩子的值

后序线索二叉树

1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 6 using namespace std; 7 8 struct TREE{ 9 int val; 10 TREE *ch[2]; 11 TREE *thread;//该节点的线索的下一个节点 12 TREE(){} 13 TREE(int val){ 14 this->val = v

二叉树中两个节点的最近公共父节点

这是京东周六的笔试题目   当时不在状态,现在想来肯定是笔试就被刷掉了,权当做个纪念吧.  这个问题可以分为三种情况来考虑: 情况一:root未知,但是每个节点都有parent指针此时可以分别从两个节点开始,沿着parent指针走向根节点,得到两个链表,然后求两个链表的第一个公共节点,这个方法很简单,不需要详细解释的. 情况二:节点只有左.右指针,没有parent指针,root已知思路:有两种情况,一是要找的这两个节点(a, b),在要遍历的节点(root)的两侧,那么这个节点就是这两个节点的最

中序线索二叉树

虽说对于二叉树的遍历操作来说非递归法使用用户自定义的栈来代替递归使用时的系统栈,可以得到不小的效率提升,但将二叉树线索化时能将用户栈也省略掉进一步提高了效率. 对于二叉树的链表结构,n个结点的二叉树有n+1个空链域(每个叶节点都有两个空链域),而线索二叉树就把这些空链域有效的利用了起来,在一般的二叉树中,我们只知道每个结点的左右孩子,并不知道某个结点在某种遍历方式下的直接前驱和直接后继,如果能够知道前驱和后继信息,就可以把二叉树看作一个链表结构,从而可以像遍历链表那样来遍历二叉树,进而提高效率.