二叉树的遍历

二叉树的遍历(Binary Tree)

在这里总结一下树的遍历方式,留作以后自己在学习使用,如有问题欢迎大家留言指正。
例子
先定义一下树的结构和基本操作(代码不加特殊说明均为此结构)

// C语言实现版
#include <stdio.h>
#include <stdlib.h>
// 定义树结构
struct node {
     int data;
     struct node* left;
     struct node* right;
};

深度优先遍历

中序遍历(Inorder)
遍历次序(Left->Root->Right) 4 2 5 1 3
算法描述
Inorder(tree)
    Inorder(left-subtree) // 遍历左子树
    Visit(root) // 打印根
    Inorder(right-subtree) // 遍历右子树
代码实现
void printInorder(struct node* node) {
     if (node == NULL)
          return;
     printInorder(node->left);
     printf("%d ", node->data);  
     printInorder(node->right);
}
非递归算法描述(栈)
Create an empty stack S.
Initialize current node as root
While stack is not NULL or current is not NULL do
    if current is not NULL then 
        Push the current node to S and set current = current->left until current is NULL
    else 
        if S is not NULL
             Pop the top item from stack.
             Print the popped item, set current = popped_item->right 

栈

代码实现
// 树结构
struct tNode {
    int data;
    struct tNode *left;
    struct tNode *right;
};

// 栈结构
struct sNode {
    struct tNode *t;
    struct sNode *next;
};

// 压栈
void push(struct sNode** top_ref, struct tNode *t) {
    struct sNode *newTNode = (struct sNode*)malloc(sizeof(struct sNode));

    newTNode->t = t;
    newTNode->next = (*top_ref);
    (*top_ref) = newTNode;
}

// 判空
bool isEmpty(struct sNode *top) {
    return (top == NULL) ? 1 : 0;
}

//弹栈
struct tNode *pop(struct sNode **top_ref) {
    struct tNode *res;
    struct sNode *top;

    if (isEmpty(*top_ref)) {
        exit(0);
    }
    else{
        top = *top_ref;
        res = top->t;
        *top_ref = top->next;
        free(top);
        return res;
    }
}

// 遍历
void inOrder(struct tNode *root) {
    struct tNode *current = root;
    struct sNode *s = NULL;

    while (current != NULL || !isEmpty(s)) {
        if (current != NULL) {
            push(&s, current);
            current = current->left;
        }
        else {
            if (!isEmpty(s)) {
                current = pop(&s);
                printf("%d ", current->data);
                current = current->right;
            }
        }
    }
}
非递归遍历(Morris Traversal)
算法描述
Initialize current as root 
While current is not NULL
   If current does not have left child
      Visit(current)
      current = current->right
   Else
      Make current as right child of the rightmost node in current's left subtree
      current = current->left
核心在于找到中序遍历下的前驱节点,即为一直遍历右儿子到其不存在
算法的时间复杂度为O(n) 空间复杂度O(1)

这里写图片描述

代码实现
// 树结构
struct tNode {
    int data;
    struct tNode* left;
    struct tNode* right;
};

void morrisTraversal(struct tNode *root) {
    struct tNode *current, *pre;

    if (!root) {
        return;
    }
    current = root;
    while (current) {
        if (!current->left) {
            printf("%d ", current->data);
            current = current->right;
        }
        else {
            pre = current->left;
            while (pre->right && pre->right != current) {
                pre = pre->right;
            }

            if (!pre->right) {
                pre->right = current;
                current = current->left;
            }
            else {
                pre->right = NULL;
                printf("%d ", current->data);
                current = current->right;
            }
        }
    }
}
先序遍历(Preorder)
遍历次序(Root->Left->Right) 1 2 4 5 3
递归算法描述
Preorder(tree)
    Visit(root) // 打印根
    Preorder(left-subtree) // 遍历左子树
    Preorder(right-subtree) // 遍历右子树
递归代码实现
void printPreorder(struct node* node) {
     if (node == NULL)
          return;
     printf("%d ", node->data);  
     printPreorder(node->left);  
     printPreorder(node->right);
}    
非递归实现(栈)
算法和中序遍历相似 在这里不过多赘述,直接贴出代码
void preOrder(struct tNode *root) {
    if (root == NULL) return;
    struct sNode *s = NULL;
    push(&s, root);

    while (!isEmpty(s)) {
        struct tNode *node = pop(&s);
        printf("%d ", node->data);

        if (node->right) push(&s, (node->right));
        if (node->left) push(&s, (node->left));
    }
}
非递归实现 (Morris Traversal)
void preOrder(struct tNode *root) {
    while (root) {
        if (!root->left) {
            printf("%d ", root->data);
            root = root->right;
        }
        else {
            struct tNode* current = root->left;
            while (current->right && current->right != root) {
                current = current->right;
            }
            if (current->right == root) {
                current->right = NULL;
                root = root->right;
            }
            else {
                printf("%d ", root->data);
                current->right = root;
                root = root->left;
            }
        }
    }
}
后序遍历(Postorder)
遍历次序(Left->Right->Root) 4 5 2 3 1
Postorder(tree)
    Postorder(left-subtree) // 遍历左子树
    Postorder(right-subtree) // 遍历右子树
    Visit(root) // 打印根
代码实现
void printPostorder(struct node* node) {
     if (node == NULL)
        return;
     printPostorder(node->left);
     printPostorder(node->right);
     printf("%d ", node->data);
}
非递归算法(双栈)
算法描述
Push root to first stack.
Loop while first stack is not empty
   Pop a node from first stack and push it to second stack
   Push left and right children of the popped node to first stack
Print contents of second stack

在这里偷一个懒,拿Python实现这个代码。

代码实现
# 树结构
class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None

def postOrder(root):
    if root is None:
        return
    s1, s2 = [], []
    s1.append(root)
    while len(s1) > 0:
        node = s1.pop()
        s2.append(node)
        if node.left is not None:
            s1.append(node.left)
        if node.right is not None:
            s1.append(node.right)
    # 直接输出s2便是结果,不弹栈了
    for node in s2:
        print node.data

下面仅用一个栈实现后序遍历

算法描述
Create an empty stack
While stack is not empty
    Do following while root is not NULL
        Push root's right child and then root to stack.
        Set root as root's left child.
    Pop an item from stack and set it as root.
        If the popped item has a right child and the right child is at top of stack, then remove the right child from stack, push the root back and set root as root's right child.
        Else print root's data and set root as NULL.

后序遍历比较麻烦具体栈的实现就省略了还是偷懒用Python实现。

def peek(stack):
    return None if len(stack) <= 0 else stack[-1]

def postOrderIterative(root):
    if root is None:
        return

    stack = []

    while(True):
        while (root):
            if root.right is not None:
                stack.append(root.right)
            stack.append(root)

            root = root.left

        root = stack.pop()

        if (root.right is not None and peek(stack) == root.right):
            stack.pop()
            stack.append(root)
            root = root.right
        else:
            print(root.data)
            root = None

        if (len(stack) <= 0):
            break
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值