樹3-二叉樹非遞迴遍歷(棧)

HIK4RU44發表於2024-04-18

樹3-二叉樹非遞迴遍歷(棧)


複製根結點, 初始值FALSE, 入棧

彈出, 如果是FALSE,

將根節點將更新為TRUE, 其子結點(初始值FALSE)一併入棧

[A,B,C] (前序遍歷, 入棧順序:C,B,A 輸出順序: A,B,C)

再彈出, 如果是TRUE則輸出


引入鏈式棧標頭檔案

#include "linkedStack.h"

鏈式棧標頭檔案

#ifndef LINKEDSTACK_H
#define LINKEDSTACK_H
#include <stdlib.h>

//鏈式棧的結點
typedef struct LinkNode{
    struct LinkNode *next;
} LinkNode;

//鏈式棧
typedef struct LinkStack{
    LinkNode head; //鏈式棧的頭結點
    int size; //棧的元素數量
} LinkStack;

//初始化
LinkStack* Init_LinkStack(){
    LinkStack *stack = (LinkStack*)malloc(sizeof(LinkStack));
    stack->head.next = NULL;
    stack->size=0;
    return stack;
};

//入棧(頭插法)
void Push_LinkStack(LinkStack* stack, LinkNode *data){
    if(stack==NULL) return;
    if(data==NULL) return;
    //插入結點的後繼指向第一個結點
    data->next = stack->head.next;
    //頭結點的後繼指向插入結點
    stack->head.next = data;
    //鏈式棧長度++
    stack->size++;
};

//返回棧頂元素
LinkNode* Top_LinkStack(LinkStack* stack){
    if(stack==NULL) return NULL;
    if(stack->size==0) return NULL;
    return stack->head.next;
};

//出棧
void Pop_LinkStack(LinkStack* stack){
    if(stack==NULL) return;
    if(stack->size==0) return;    
    //第一個有效結點
    LinkNode *pNext = stack->head.next;
    //刪除第一個有效結點(跳過)
    stack->head.next =  pNext->next;
    //鏈式棧長度--
    stack->size--;
};

//返回棧元素個數
int Size_LinkStack(LinkStack* stack){
    if(stack==NULL) return -1;
    return stack->size;
};

//清空
void Clear_LinkStack(LinkStack* stack){
    if(stack==NULL) return;
    stack->head.next = NULL;
    stack->size = 0;
};

//銷燬
void FreeSpace_LinkStack(LinkStack*

二叉樹結點

//二叉樹結點
typedef struct BinaryNode{
    char ch;
    struct BinaryNode *lChild;
    struct BinaryNode *rChild;
} BinaryNode;

鏈式棧結點

//棧結點
typedef struct BiTreeStackNode{
    LinkNode node; //支援鏈式棧的必要部分  (為什麼不是指標?)
    BinaryNode* root; //二叉樹結點
    int flag; 
} BiTreeStackNode;

建立棧中的結點

//建立棧中的結點
BiTreeStackNode* CreateBiTreeStackNode(BinaryNode *node, int flag){
    //將二叉樹結點作為元素壓入棧中
    BiTreeStackNode *newNode = (BiTreeStackNode*)malloc(sizeof(BiTreeStackNode));
    newNode->root = node;
    newNode->flag = flag;
    return newNode;
}

非遞迴遍歷

//非遞迴遍歷
void NonRecursion(BinaryNode* root){
    //建立棧 
    LinkStack *stack = Init_LinkStack();
    //把根節點扔進棧中(初始化為FALSE)
    Push_LinkStack(stack, (LinkNode*)CreateBiTreeStackNode(root, MY_FALSE));
    //棧非空時, 遍歷
    while(Size_LinkStack(stack)>0){
        //取出棧頂元素
        BiTreeStackNode *node = (BiTreeStackNode*)Top_LinkStack(stack);
        //彈出棧頂元素
        Pop_LinkStack(stack);
        //是否彈出的結點是否為空, 為空則跳過這次迴圈
        if(node->root==NULL){
            continue;
        }
        //判斷結點的flag, 如果true, 輸出
        if(node->flag==MY_TRUE){
            cout << node->root->ch << " ";
        }else{// false, 更新根節點flag+左右子樹壓棧
            //當前結點的右結點入棧
            Push_LinkStack(stack, (LinkNode*)CreateBiTreeStackNode(node->root->rChild, MY_FALSE));
            //當前結點的左結點入棧
            Push_LinkStack(stack, (LinkNode*)CreateBiTreeStackNode(node->root->lChild, MY_FALSE));
            //根節點更新為TRUE
            node->flag = MY_TRUE;
            Push_LinkStack(stack, (LinkNode*)node);
        }
    }
    cout << endl;
}

釋放二叉樹

//釋放二叉樹
void FreeSpaceBinaryTree(BinaryNode* root){
    if(root==NULL) return;
    //釋放左子樹
    FreeSpaceBinaryTree(root->lChild);
    //釋放右子樹 
    FreeSpaceBinaryTree(root->rChild);
    //釋放當前結點
    free(root);
}

建立二叉樹

void CreateBinaryTree(){
    //建立結點
    BinaryNode node1 = {'A',NULL,NULL};
    BinaryNode node2 = {'B',NULL,NULL};
    BinaryNode node3 = {'C',NULL,NULL};
    BinaryNode node4 = {'D',NULL,NULL};
    BinaryNode node5 = {'E',NULL,NULL};
    BinaryNode node6 = {'F',NULL,NULL};
    BinaryNode node7 = {'G',NULL,NULL};
    BinaryNode node8 = {'H',NULL,NULL};
    //建立結點關係
    node1.lChild = &node2;
    node2.rChild = &node3;
    node3.lChild = &node4;
    node3.rChild = &node5;
    node1.rChild = &node6;
    node6.rChild = &node7;
    node7.rChild = &node8;

    //二叉樹非遞迴輸出 
    NonRecursion(&node1);

    FreeSpaceBinaryTree(&node1);
}

測試

int main(){
    CreateBinaryTree();
    cout << endl;

    system("pause");
    return 0;
}

相關文章