二叉樹非遞歸遍歷(前中後)

樹(二叉樹)的建立和遍歷算法(二)

(這是剛學習時轉的,後來又發現了一種新的寫法,一個統一的函數就能實現二叉樹的前中後的遍歷鏈接:

點擊打開鏈接      

上篇樹(二叉樹)的建立和遍歷算法(一)對二叉樹的遍歷是遞歸的方法,這裏利用非遞歸的方法實現二叉樹的遍歷。首先要看懂上篇樹(二叉樹)的建立和遍歷算法(一)

       關於二叉樹的建立就不具體講了。看上篇就OK了,那就直接見代碼,非遞歸的方法實現對其的遍歷。

複製代碼
//非遞歸方式前序遍歷
/* 思路:將T入棧,遍歷左子樹;遍歷完左子樹返回時,棧頂元素應爲T,出棧,再先序遍歷T的右子樹。*/
void PreOrder(BiTree T){
    stack<BiTree> stack;
    //p是遍歷指針  
    BiTree p = T;
    //p不爲空或者棧不空時循環
    while (p || !stack.empty())
{
        if (p != NULL)
                 {
            //存入棧中  
            stack.push(p);
            //對樹中的結點進行操作
            operation1(p->data);
             //遍歷左子樹  
            p = p->lchild;
         }
        else
                {
                 //退棧  
            p = stack.top();
            stack.pop();
            //訪問右子樹  
            p = p->rchild;
        }
    } 
}
//非遞歸中序遍歷
void InOrder(BiTree T)
{
    stack<BiTree> stack;
    //p是遍歷指針  
    BiTree p = T;
    //p不爲空或者棧不空時循環  
    while (p || !stack.empty())
       {
        if (p != NULL)
                  {
            //存入棧中  
            stack.push(p);
            //遍歷左子樹  
            p = p->lchild;
         }
        else
                {
            //退棧
            p = stack.top();
            operation1(p->data); //對樹中的結點進行操作
            stack.pop();
            //訪問右子樹  
            p = p->rchild;
        }
    } 
}
//非遞歸後序遍歷
typedef struct BiTNodePost{
    BiTree biTree;
    char tag;
}BiTNodePost, *BiTreePost;

void PostOrder(BiTree T)
{
    stack<BiTreePost> stack;
    //p是遍歷指針  
    BiTree p = T;
    BiTreePost BT;
    //棧不空或者p不空時循環  
    while (p != NULL || !stack.empty())
        {
        //遍歷左子樹  
        while (p != NULL)
               {
            BT = (BiTreePost)malloc(sizeof(BiTNodePost));
            BT->biTree = p;
            //訪問過左子樹  
            BT->tag = 'L';
            stack.push(BT);
            p = p->lchild;
        }
        //左右子樹訪問完畢訪問根節點  
        while (!stack.empty() && (stack.top())->tag == 'R')
                {
            BT = stack.top();
            //退棧  
            stack.pop();
            BT->biTree;
            cout<<BT->biTree->data<<" ";
        }
        //遍歷右子樹  
        if (!stack.empty())
                {
            BT = stack.top();
            //訪問過右子樹  
            BT->tag = 'R';
            p = BT->biTree;
            p = p->rchild;
        }
    }
}
//層次遍歷  
void LevelOrder(BiTree T)
{
    BiTree p = T; 
    queue<BiTree> queue;
    //根節點入隊  
    queue.push(p);
    //隊列不空循環  
    while (!queue.empty())
       {
        //對頭元素出隊  
        p = queue.front();
        //訪問p指向的結點  
        operation1(p->data);
        //退出隊列  
        queue.pop();
        //左孩子不爲空,將左孩子入隊  
        if (p->lchild != NULL)
                {
            queue.push(p->lchild);
        }
        //右孩子不空,將右孩子入隊  
        if (p->rchild != NULL)
                {
            queue.push(p->rchild);
        }
    }
}
複製代碼

1.完整的代碼:

複製代碼
#include<iostream>
#include<stdlib.h>
#include<stack>
#include<queue>
using namespace std;

typedef char ElemType;

//二叉樹的二叉鏈表結構,也就是二叉樹的存儲結構,1個數據域,2個指針域(分別指向左右孩子)

typedef  struct BiTNode
{
    ElemType data;
    struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

//二叉樹的建立,按前序遍歷的方式建立二叉樹,當然也可以以中序或後序的方式建立二叉樹
void CreateBiTree(BiTree *T)
{
    ElemType ch;
    cin >> ch;
    if (ch == '#')
        *T = NULL;  //保證是葉結點
    else
    {
        *T = (BiTree)malloc(sizeof(BiTNode));
        //if (!*T)
            //exit(OVERFLOW); //內存分配失敗則退出。
        (*T)->data = ch;//生成結點
        CreateBiTree(&(*T)->lchild);//構造左子樹
        CreateBiTree(&(*T)->rchild);//構造右子樹    
    }
}

//表示對遍歷到的結點數據進行的處理操作,此處操作是將樹結點前序遍歷輸出
void operation1(ElemType ch)
{
    cout << ch << " ";
}
//此處在輸出的基礎上,並輸出層數
void operation2(ElemType ch, int level)
{
       cout << ch << "在第" << level << "" << "  ";
}


//遞歸方式前序遍歷二叉樹
void PreOrderTraverse(BiTree T, int level)
{
    if (T == NULL)
        return;
/*此處表示對遍歷的樹結點進行的操作,根據你自己的要求進行操作,這裏只是輸出了結點的數據*/
    operation1(T->data);
    //operation2(T->data, level); //輸出了層數

    PreOrderTraverse(T->lchild, level + 1);
    PreOrderTraverse(T->rchild, level + 1);
}

//遞歸方式中序遍歷二叉樹

void InOrderTraverse(BiTree T,int level)
{
if(T==NULL)
return;
InOrderTraverse(T->lchild,level+1);

operation1(T->data);
//operation2(T->data, level); //輸出了層數

InOrderTraverse(T->rchild,level+1);
}

//遞歸方式後序遍歷二叉樹

void PostOrderTraverse(BiTree T,int level)
{
if(T==NULL)
return;
PostOrderTraverse(T->lchild,level+1);
PostOrderTraverse(T->rchild,level+1);

operation1(T->data);
//operation2(T->data, level); //輸出了層數
}

//非遞歸方式前序遍歷
/* 思路:將T入棧,遍歷左子樹;遍歷完左子樹返回時,棧頂元素應爲T,出棧,再先序遍歷T的右子樹。*/
void PreOrder(BiTree T){
    stack<BiTree> stack;
    //p是遍歷指針  
    BiTree p = T;
    //p不爲空或者棧不空時循環
    while (p || !stack.empty())
{
        if (p != NULL)
                 {
            //存入棧中  
            stack.push(p);
            //對樹中的結點進行操作
            operation1(p->data);
             //遍歷左子樹  
            p = p->lchild;
         }
        else
                {
                 //退棧  
            p = stack.top();
            stack.pop();
            //訪問右子樹  
            p = p->rchild;
        }
    } 
}
//非遞歸中序遍歷
void InOrder(BiTree T)
{
    stack<BiTree> stack;
    //p是遍歷指針  
    BiTree p = T;
    //p不爲空或者棧不空時循環  
    while (p || !stack.empty())
       {
        if (p != NULL)
                  {
            //存入棧中  
            stack.push(p);
            //遍歷左子樹  
            p = p->lchild;
         }
        else
                {
            //退棧
            p = stack.top();
            operation1(p->data); //對樹中的結點進行操作
            stack.pop();
            //訪問右子樹  
            p = p->rchild;
        }
    } 
}
//非遞歸後序遍歷
typedef struct BiTNodePost{
    BiTree biTree;
    char tag;
}BiTNodePost, *BiTreePost;

void PostOrder(BiTree T)
{
    stack<BiTreePost> stack;
    //p是遍歷指針  
    BiTree p = T;
    BiTreePost BT;
    //棧不空或者p不空時循環  
    while (p != NULL || !stack.empty())
        {
        //遍歷左子樹  
        while (p != NULL)
               {
            BT = (BiTreePost)malloc(sizeof(BiTNodePost));
            BT->biTree = p;
            //訪問過左子樹  
            BT->tag = 'L';
            stack.push(BT);
            p = p->lchild;
        }
        //左右子樹訪問完畢訪問根節點  
        while (!stack.empty() && (stack.top())->tag == 'R')
                {
            BT = stack.top();
            //退棧  
            stack.pop();
            BT->biTree;
            cout<<BT->biTree->data<<" ";
        }
        //遍歷右子樹  
        if (!stack.empty())
                {
            BT = stack.top();
            //訪問過右子樹  
            BT->tag = 'R';
            p = BT->biTree;
            p = p->rchild;
        }
    }
}
//層次遍歷  
void LevelOrder(BiTree T)
{
    BiTree p = T; 
    queue<BiTree> queue;
    //根節點入隊  
    queue.push(p);
    //隊列不空循環  
    while (!queue.empty())
       {
        //對頭元素出隊  
        p = queue.front();
        //訪問p指向的結點  
        operation1(p->data);
        //退出隊列  
        queue.pop();
        //左孩子不爲空,將左孩子入隊  
        if (p->lchild != NULL)
                {
            queue.push(p->lchild);
        }
        //右孩子不空,將右孩子入隊  
        if (p->rchild != NULL)
                {
            queue.push(p->rchild);
        }
    }
}
int main()
{
    int level = 1; //表層數
    BiTree T = NULL;
    cout << "請以前序遍歷的方式輸入擴展二叉樹:"; //類似輸入AB#D##C##
    CreateBiTree(&T);// 建立二叉樹,沒有樹,怎麼遍歷
    cout << "遞歸前序遍歷輸出爲:" << endl;
    PreOrderTraverse(T, level);//進行前序遍歷,其中operation1()和operation2()函數表示對遍歷的結點數據進行的處理操作
    cout << endl;
    cout << "遞歸中序遍歷輸出爲:" << endl;
    InOrderTraverse(T, level);
    cout << endl;
    cout << "遞歸後序遍歷輸出爲:" << endl;
    PostOrderTraverse(T, level);
    cout << endl;
        cout<<"非遞歸前序遍歷輸出爲:"<<endl;
        PreOrder(T);
        cout<<endl;
        cout<<"非遞歸前序遍歷輸出爲:"<<endl;
        InOrder(T);
        cout<<endl;
        cout<<"非遞歸前序遍歷輸出爲:"<<endl;
        PostOrder(T);
        cout<<endl;
        cout<<"層序遍歷輸出爲:"<<endl;
        LevelOrder(T);
        cout<<endl;
    return 0;
}
複製代碼

2. 運行結果:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章