1. 程式人生 > >二叉樹中輸出節點的祖先以及找最近公共祖先

二叉樹中輸出節點的祖先以及找最近公共祖先

問題1

給定一顆二叉樹,給定某個結點X的值,要求打印出該結點的祖先。

思路

想想上一篇中有講到後序遍歷的非遞迴演算法,其中棧裡面儲存的正是從根結點到當前結點的一條路徑。如果當前結點就是要找的結點X的話,那麼棧裡面儲存的就是該結點的所有祖先,依次輸出即可。如果當前結點不是要找的結點X,如果標記位為1則繼續遍歷,否足則對該結點進行空遍歷(即將該結點彈出棧)

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <malloc.h>
#include <stack>
#include <queue> #include <bits/stdc++.h> using namespace std; typedef struct BiTNode{ char data; struct BiTNode *left,*right; }BiTNode,*BiTree; BiTree build() { char c; BiTree st = nullptr; c=getchar(); if(c!='#') { st = new BiTNode(); st ->data = c;//已知為先序遍歷,先填充根節點
st ->left = build();//遞迴形式填充左分支 st ->right = build();//遞迴形式填充左分支 } return st; } void visit(BiTNode *x) { cout<<x->data<<' '; } //後序非遞迴 void backVisitStack(BiTree root,char x) { BiTNode* p = root; stack<pair<BiTNode*,int>>st; while
(p != nullptr || !st.empty()){ while(p!=nullptr && p->data != x){ st.push(make_pair(p,1)); p = p->left; } if(p != nullptr && p->data == x){ while(!st.empty()){ visit(st.top().first); st.pop(); } return ; } while(!st.empty() && st.top().second == 2) st.pop(); if(!st.empty()){ st.top().second = 2; p = st.top().first->right; } } cout << endl; } /* 樹的結構 A / \ B C / \ / D E F / \ G H */ //先序序列 ABDG###E#H##CF### // 根據先序 建樹 int main() { BiTree bt; bt = build(); char x = 'H'; backVisitStack(bt,x); return 0; }

問題2

給定一棵二叉樹,以及兩個結點的值,找出這兩個結點的最近公共祖先

思路

還是利用非遞迴的後序遍歷,不過可以假設x結點在y結點的左邊,當遍歷到x結點時,利用一個輔助棧將其祖先儲存下來,繼續遍歷到y,然後從棧頂開始找兩個棧中第一個相等的結點就是x,y的最近的公共祖先

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <malloc.h>
#include <stack>
#include <queue>
#include <bits/stdc++.h>

using namespace std;


typedef struct BiTNode{
    char data;
    struct BiTNode *left,*right;
}BiTNode,*BiTree;

typedef struct{
    BiTree t;
    int tag;
}Stack;


BiTree build()
{
    char c;
    BiTree st = nullptr;
    c=getchar();
    if(c!='#')

    {

        st = new BiTNode();
        st ->data = c;//已知為先序遍歷,先填充根節點
        st ->left = build();//遞迴形式填充左分支
        st ->right = build();//遞迴形式填充左分支
    }
    return st;
}

void visit(BiTNode *x)
{

    cout<<x->data<<' ';
}

//後序非遞迴
void backVisitStack(BiTree root,char x ,char y)
{

    BiTNode* p = root;
    Stack s[100],s1[100];
    int top = 0;
    int top1 = 0;

    while( p != nullptr || top > 0){
        while(p != nullptr){
                s[++top].t = p;
                s[top].tag = 1;
                p = p->left;
        }
        while(top != 0 && s[top].tag == 2){
            if( s[top].t->data == x){
                for(int j = 1; j <= top; ++j)
                    s1[j] = s[j];
                    top1 = top;
            }
            if(s[top].t->data == y){
                for(int i = top; i > 0; --i){
                    for(int j = top1; j > 0; --j){
                        if(s[i].t->data == s1[j].t->data){
                            visit(s[i].t);
                            return ;
                        }
                    }
                }
            }

            --top;
        }

        if(top > 0){
            s[top].tag = 2;
            p = s[top].t->right;
        }
    }


    cout << endl;
}

/* 樹的結構
        A
      /   \
     B     C
    / \   /
   D   E  F
  /     \
 G       H
*/



//先序序列 ABDG###E#H##CF###

// 根據先序 建樹


int main()
{

    BiTree bt;
    bt = build();

    char x = 'G';
    char y = 'H';
    backVisitStack(bt,x,y);

    return 0;
}