C++學習---二叉樹的輸入及非遞歸遍歷


二叉樹的二叉鏈表存儲表示如下

//二叉樹的二叉鏈表存儲表示
typedef struct BiTNode {
    char data;//結點數據域
    struct BiTNode* lchild, * rchild;//左右孩子指針
}*BiTree;

根據括號表示法的字符串創建樹(括號里的表示括號前結點的子結點,‘,’號左邊是左子結點,右邊是右子結點)

比如:a(b(d,e),c(f,g(h,i)))

表示的則是

 

  

//創建樹
void CreateBiTree(BiTree& T)
{
    stack<BiTNode*> s;//用於確定需要操作的結點
    BiTNode* p=NULL;
    int i = 0;
    bool child_Direct;//0表示左子結點,1表示右子結點
    //按先序次序輸入二叉樹中結點的值(一個字符),創建二叉鏈表表示的二叉樹T
    string TreeStr;
    cin >> TreeStr;
    while (TreeStr[i] != '\0') {
        switch (TreeStr[i])
        {
        case'('://左子結點
            s.push(p);
            child_Direct = false;
            break;
        case')':
            s.pop();
        case','://右子結點
            child_Direct = true;
            break;

        default:
            p = new BiTNode;
            p->data = TreeStr[i];
            p->lchild = p->rchild = NULL;
            if (T == NULL)//若根節點為空則p指向根節點
                T = p;
            else {
                if (!child_Direct)
                    s.top()->lchild = p;
                else
                    s.top()->rchild = p;
            }
            break;
        }
        i++;
    }

}

  

 非遞歸先序、中序、后序遍歷

先序:

void PreOrderTraverse(BiTree T) {
    stack<BiTNode*> s;
    BiTNode* p = T, * q = new BiTNode();
    while (p != NULL || !s.empty()) {
        if (p)//p非空
        {
            cout << p->data;
            s.push(p);//根指針入棧
            p = p->lchild;//遍歷左子樹
        }
        else {
            p = s.top();
            s.pop();
            p = p->rchild;//遍歷右子樹
        }
    }
}

  

中序:

//中序遍歷
void InOrderTraverse(BiTree T) {
    stack<BiTNode*> s;
    BiTNode* p = T, * q = new BiTNode();
    while (p != NULL || !s.empty()) {
        if (p)//p非空
        {
            s.push(p);//根指針入棧
            p = p->lchild;//遍歷左子樹
        }
        else {
            p = s.top();
            s.pop();
            cout << p->data;
            p = p->rchild;//遍歷右子樹
        }
    }
}

  

后序:

//后序遍歷
void PostOrderTraverse(BiTree T) {
    BiTNode* p = T, * r = NULL;
    stack<BiTNode*> s;
    while (p != NULL || !s.empty()) {
        if (p != NULL) {//走到最左邊
            s.push(p);
            p = p->lchild;
        }
        else {
            p = s.top();
            if (p->rchild != NULL && p->rchild != r)//右子樹存在,未被訪問
                p = p->rchild;
            else {
                s.pop();
                cout << p->data;
                r = p;//記錄最近訪問過的節點
                p = NULL;//節點訪問完后,重置p指針
            }
        }//else
    }//while
    
}

完整代碼

#include <iostream>
#include <stack>
#include <string>
using namespace std;

//二叉樹的二叉鏈表存儲表示
typedef struct BiTNode {
    char data;//結點數據域
    struct BiTNode* lchild, * rchild;//左右孩子指針
}*BiTree;

void Initial(BiTree& T) {
    T = new BiTNode;
    T = NULL;
}
//創建樹
void CreateBiTree(BiTree& T)
{
    stack<BiTNode*> s;//用於確定需要操作的結點
    BiTNode* p=NULL;
    int i = 0;
    bool child_Direct;//0表示左子結點,1表示右子結點
    //按先序次序輸入二叉樹中結點的值(一個字符),創建二叉鏈表表示的二叉樹T
    string TreeStr;
    cin >> TreeStr;
    while (TreeStr[i] != '\0') {
        switch (TreeStr[i])
        {
        case'('://左子結點
            s.push(p);
            child_Direct = false;
            break;
        case')':
            s.pop();
        case','://右子結點
            child_Direct = true;
            break;

        default:
            p = new BiTNode;
            p->data = TreeStr[i];
            p->lchild = p->rchild = NULL;
            if (T == NULL)//若根節點為空則p指向根節點
                T = p;
            else {
                if (!child_Direct)
                    s.top()->lchild = p;
                else
                    s.top()->rchild = p;
            }
            break;
        }
        i++;
    }

}
//以括號表示法輸出二叉樹
void DispBTNode(BiTNode *&b)  
{
    if (b != NULL)
    {
        cout<<b->data;
        if (b->lchild != NULL || b->rchild != NULL)
        {
            cout<<"(";
            DispBTNode(b->lchild);
            if (b->rchild != NULL) cout<<(",");
            DispBTNode(b->rchild);
            cout<<")";
        }
    }
}

#pragma region 遞歸遍歷
//先序
void PreOrderTraverseR(BiTree T) {
    if (T != NULL) {
        cout << T->data;
        PreOrderTraverseR(T->lchild);
        PreOrderTraverseR(T->rchild);
    }
}
//中序
void InOrderTraverseR(BiTree T) {
    if (T != NULL) {
        InOrderTraverseR(T->lchild);
        cout << T->data;
        InOrderTraverseR(T->rchild);
    }
}
//后序
void PostOrderTraverseR(BiTree T) {
    if (T != NULL) {
        PostOrderTraverseR(T->lchild);
        PostOrderTraverseR(T->rchild);
        cout << T->data;
    }
}
#pragma endregion


#pragma region 非遞歸遍歷
//先序遍歷
void PreOrderTraverse(BiTree T) {
    stack<BiTNode*> s;
    BiTNode* p = T, * q = new BiTNode();
    while (p != NULL || !s.empty()) {
        if (p)//p非空
        {
            cout << p->data;
            s.push(p);//根指針入棧
            p = p->lchild;//遍歷左子樹
        }
        else {
            p = s.top();
            s.pop();
            p = p->rchild;//遍歷右子樹
        }
    }
}
//中序遍歷
void InOrderTraverse(BiTree T) {
    stack<BiTNode*> s;
    BiTNode* p = T, * q = new BiTNode();
    while (p != NULL || !s.empty()) {
        if (p)//p非空
        {
            s.push(p);//根指針入棧
            p = p->lchild;//遍歷左子樹
        }
        else {
            p = s.top();
            s.pop();
            cout << p->data;
            p = p->rchild;//遍歷右子樹
        }
    }
}
//后序遍歷
void PostOrderTraverse(BiTree T) {
    BiTNode* p = T, * r = NULL;
    stack<BiTNode*> s;
    while (p != NULL || !s.empty()) {
        if (p != NULL) {//走到最左邊
            s.push(p);
            p = p->lchild;
        }
        else {
            p = s.top();
            if (p->rchild != NULL && p->rchild != r)//右子樹存在,未被訪問
                p = p->rchild;
            else {
                s.pop();
                cout << p->data;
                r = p;//記錄最近訪問過的節點
                p = NULL;//節點訪問完后,重置p指針
            }
        }//else
    }//while
    
}
#pragma endregion
int main()
{
    BiTree b;
    Initial(b);
    //創建樹
    CreateBiTree(b);
    //先序遍歷
    cout << "先序遍歷:";
    PreOrderTraverse(b);
    cout << endl;
    //中序遍歷
    cout << "中序遍歷:";
    InOrderTraverse(b);
    cout << endl;
    //后序遍歷
    cout << "后序遍歷:";
    PostOrderTraverse(b);
}

  

程序示例:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM