1. 程式人生 > >非遞迴建立二叉樹 先序 中序 後序遍歷

非遞迴建立二叉樹 先序 中序 後序遍歷

思想:用”棧”來消除遞迴。

主要是建立的過程,剛開始卡到了如果遇到’#’,那麼在else中間出棧之後還需要讀一個元素,這樣在遇到連續的”#”之後,退棧並不能達到合適的位置,最後聽了“巔峰”的建議,還是設定了flag,解決了問題,下面解釋下建立過程的思想:

1:正常情況下以先序的方式輸入串。一個一個字元讀取;如果第一個字元不為“#”,先將它入棧,即我們的根。
2:初始化flag = 0,如果沒有讀到“#”,就開闢節點,獲取棧頂元素,將字元存入棧頂元素的lchild,並且將它入棧。
3:要是讀到”#”,就將flag = 1;重新讀取一個元素,若不為“#”,就將它存入棧頂元素的rchild,然後將flag = 0;如果讀到“#”後接下來又讀到”#”,那麼就出棧一個元素,並且判斷當前棧頂的rchild是不是剛才出棧的元素。如果是剛才出棧的元素並且棧不為空,那就說明當前棧頂元素的左右子樹都已經建立完畢,那就再出一個,再判斷,直到不是才說明我們的將此時根的左邊才完全建立好了

,要是一直出到棧為空,那就說明完全建立完畢。

下面附上程式碼:


#include<stdio.h>
#include<stdlib.h>
#include "my_stack.h"

Tree creat(Head);
void PreOrder(Tree,Head);
void InOrder(Tree,Head);
void LastOrder(Tree,Head);

void LastOrder(Tree root,Head head)
{
    Tree q = NULL;
    while(root || head->top != -1
) { if(root) { push(head,root); root = root->lchild; } //每次需要先走到最左邊 else { root = gettop(head); if((root->rchild == NULL )|| (root->rchild == q)) { //取棧頂判斷 //如果郵孩子為空或者右孩子剛被訪問過,說明上一個元素的公恩兩個已經結束了,那就訪問根,
root = pop(head); printf("%c ",root->data); q = root; //這一步儲存當前根的位置,以便下一次判斷 root = NULL; //下一次直接判斷 } else { root = root->rchild; //否則左邊完畢就往右邊走。 } } } } void InOrder(Tree root,Head head) { while(root || head->top != -1) { if(root) { push(head,root); root = root->lchild; } else { root = pop(head); printf("%c ",root->data); root = root->rchild; } } } void PreOrder(Tree root,Head head) { while(root || head->top != -1) { if(root) { printf("%c ",root->data); push(head,root); root = root->lchild; } else { root = pop(head); root = root->rchild; } } } Tree creat(Head head) { Tree p,q; Tree root = NULL; char ch; int flag = 0; ch = getchar(); if(ch == '#') { return 0; } root = (Tree)malloc(sizeof(tree)); //為第一個節點申請空間並且入棧 p = root; p->data = ch; push(head,p); while(head->top != -1 || ch != '#') { ch = getchar(); if(ch == '#' && flag == 0) { //如果給右孩子填過值,那下面就走左邊 flag = 1; } else if(ch == '#' && flag == 1) { //連續讀到兩個#,那就邊判斷邊將右孩子和棧頂右孩子一樣的出棧, //說明右邊這些部分已經結束 p = pop(head); while(head->top != -1 && gettop(head)->rchild == p) { p = pop(head); } } else { q = (Tree)malloc(sizeof(tree)); q->data = ch; if(flag == 0) { //正常情況先訪問左邊 p = gettop(head); push(head,q); p->lchild = q; } if(flag == 1) { //要是讀到'#'就來這一句。 p = gettop(head); p->rchild = q; push(head,q); flag = 0; } } } return root; } int main(int argc,char *argv[]) { Tree root = NULL; Head head = initstack(head); printf("非遞迴建樹:\n"); root = creat(head); printf("非遞迴先序遍歷:\n"); PreOrder(root,head); printf("\n"); printf("非遞迴中序遍歷:\n"); InOrder(root,head); printf("\n"); printf("非遞迴後序遍歷:\n"); LastOrder(root,head); printf("\n"); }