非遞迴建立二叉樹 先序 中序 後序遍歷
阿新 • • 發佈:2018-12-22
思想:用”棧”來消除遞迴。
主要是建立的過程,剛開始卡到了如果遇到’#’,那麼在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");
}