算法实现之二叉树的前序、中序、后序递归和非递归遍历以及层序遍历

本文深入探讨了二叉树的四种主要遍历方式:前序遍历、中序遍历、后序遍历和层序遍历。通过递归和非递归方式实现了遍历算法,并提供了一个具体的二叉树实例进行演示。

概述

二叉树是每个节点最多有两个子树的树结构。通常子树被称作左子树右子树

二叉树的遍历通常分为:前序遍历、中序遍历、后序遍历和层序遍历

前序遍历

前序递归遍历算法:访问根结点-->递归遍历根结点的左子树-->递归遍历根结点的右子树

中序遍历

中序递归遍历算法:递归遍历根结点的左子树-->访问根结点-->递归遍历根结点的右子树

后序遍历

后序递归遍历算法:递归遍历根结点的左子树-->递归遍历根结点的右子树-->访问根结点

二叉树节点

//二叉树节点
public class BinaryTreeNode {

    private Object data;

    private BinaryTreeNode left;

    private BinaryTreeNode right;

    public BinaryTreeNode() {

    }

    public BinaryTreeNode(Object data, BinaryTreeNode left, BinaryTreeNode right) {
        this.data = data;
        this.left = left;
        this.right = right;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public BinaryTreeNode getLeft() {
        return left;
    }

    public void setLeft(BinaryTreeNode left) {
        this.left = left;
    }

    public BinaryTreeNode getRight() {
        return right;
    }

    public void setRight(BinaryTreeNode right) {
        this.right = right;
    }
}

前序遍历

//前序遍历递归的方式
public void preOrder(BinaryTreeNode root) {
    if (null != root) {
        System.out.print(root.getData() + "\t");
        preOrder(root.getLeft());
        preOrder(root.getRight());
    }
}

//前序遍历非递归的方式
public void preOrderNonRecursive(BinaryTreeNode root) {
    Stack<BinaryTreeNode> stack = new Stack<BinaryTreeNode>();
    while (true) {
        while (root != null) {
            System.out.print(root.getData() + "\t");
            stack.push(root);
            root = root.getLeft();
        }
        if (stack.isEmpty()) break;
        root = stack.pop();
        root = root.getRight();
    }
}

中序遍历

//中序遍历采用递归的方式
public void inOrder(BinaryTreeNode root) {
    if (null != root) {
        inOrder(root.getLeft());
        System.out.print(root.getData() + "\t");
        inOrder(root.getRight());
    }
}

//中序遍历采用非递归的方式
public void inOrderNonRecursive(BinaryTreeNode root) {
    Stack<BinaryTreeNode> stack = new Stack<BinaryTreeNode>();
    while (true) {
        while (root != null) {
            stack.push(root);
            root = root.getLeft();
        }
        if (stack.isEmpty()) break;
        root = stack.pop();
        System.out.print(root.getData() + "\t");
        root = root.getRight();
    }
}

后序遍历

//后序遍历采用递归的方式
public void postOrder(BinaryTreeNode root) {
    if (root != null) {
        postOrder(root.getLeft());
        postOrder(root.getRight());
        System.out.print(root.getData() + "\t");
    }
}

//后序遍历采用非递归的方式
public void postOrderNonRecursive(BinaryTreeNode root) {
    Stack<BinaryTreeNode> stack = new Stack<BinaryTreeNode>();
    while (true) {
        if (root != null) {
            stack.push(root);
            root = root.getLeft();
        } else {
            if (stack.isEmpty()) return;

            if (null == stack.lastElement().getRight()) {
                root = stack.pop();
                System.out.print(root.getData() + "\t");
                while (root == stack.lastElement().getRight()) {
                    System.out.print(stack.lastElement().getData() + "\t");
                    root = stack.pop();
                    if (stack.isEmpty()) {
                        break;
                    }
                }
            }

            if (!stack.isEmpty())
                root = stack.lastElement().getRight();
            else
                root = null;
        }
    }
}

层序遍历

//层序遍历
public void levelOrder(BinaryTreeNode root) {
    BinaryTreeNode temp;
    Queue<BinaryTreeNode> queue = new LinkedList<BinaryTreeNode>();
    queue.offer(root);
    while (!queue.isEmpty()) {
        temp = queue.poll();
        System.out.print(temp.getData() + "\t");
        if (null != temp.getLeft())
            queue.offer(temp.getLeft());
        if (null != temp.getRight()) {
            queue.offer(temp.getRight());
        }
    }
}

模拟二叉树实现

public static void main(String[] args) {
    //模拟生成上图的二叉树
    BinaryTreeNode nodeF = new BinaryTreeNode("F", null, null);
    BinaryTreeNode nodeE = new BinaryTreeNode("E", null, nodeF);
    BinaryTreeNode nodeD = new BinaryTreeNode("D", null, null);
    BinaryTreeNode nodeC = new BinaryTreeNode("C", null, null);
    BinaryTreeNode nodeB = new BinaryTreeNode("B", nodeC, nodeD);
    BinaryTreeNode nodeA = new BinaryTreeNode("A", nodeB, nodeE);

    BinaryTree tree = new BinaryTree();
    //采用递归的方式进行前序遍历
    System.out.println("-----前序遍历------");
    tree.preOrder(nodeA);
    System.out.println();
    //采用非递归的方式进行前序遍历
    tree.preOrderNonRecursive(nodeA);
    System.out.println();


    //采用递归的方式进行遍历
    System.out.println("-----中序遍历------");
    tree.inOrder(nodeA);
    System.out.println();
    //采用非递归的方式遍历
    tree.inOrderNonRecursive(nodeA);
    System.out.println();

    //采用递归的方式进行遍历
    System.out.println("-----后序遍历------");
    tree.postOrder(nodeA);
    System.out.println();
    //采用非递归的方式遍历
    tree.postOrderNonRecursive(nodeA);
    System.out.println();

    //采用递归的方式进行遍历
    System.out.println("-----层序遍历------");
    tree.levelOrder(nodeA);
    System.out.println();
}

输出如下:

-----前序遍历------
A	B	C	D	E	F
A	B	C	D	E	F
-----中序遍历------
C	B	D	A	E	F
C	B	D	A	E	F
-----后序遍历------
C	D	B	F	E	A
C	D	B	F	E	A
-----层序遍历------
A	B	E	C	D	F

参考

https://www.cnblogs.com/qiuyong/p/6675492.html

在C语言中,非递归实现叉树前序、中后序遍历,通常会使用栈数据结构来辅助。下面我会分别给出三种遍历非递归算法: ### 1. 前序遍历 (Preorder Traversal) 前序遍历是:根节点 -> 左子 -> 右子非递归版本通过栈保存访问路径。 ```c void preOrder(Node* root) { Stack *stack = createStack(); // 创建空栈 if (root != NULL) { push(stack, root); // 将根节点压入栈 while (!isEmpty(stack)) { Node* node = pop(stack); // 打印当前节点 print(node->data); // 如果左子节点存在,压入栈 if (node->left != NULL) push(stack, node->left); // 如果右子节点存在,压入栈 if (node->right != NULL) push(stack, node->right); } } } ``` ### 2. 中遍历 (Inorder Traversal) 中遍历是:左子 -> 根节点 -> 右子。这里同样借助栈,先处理左子。 ```c void inOrder(Node* root) { Stack *stack = createStack(); Node* curr = root; while (curr != NULL || !isEmpty(stack)) { // 遍历左子 while (curr != NULL) { push(stack, curr); curr = curr->left; } curr = pop(stack); // 打印当前节点 print(curr->data); curr = curr->right; // 移动到右子 } } ``` ### 3. 后序遍历 (Postorder Traversal) 后序遍历是:左子 -> 右子 -> 根节点。这里需要用到两个栈,先存储节点,然后按照相反的顺出栈。 ```c void postOrder(Node* root) { Stack *stack1 = createStack(), *stack2 = createStack(); stack1 = pushAndPop(root, stack1, stack2); // 先将根节点压入第二个栈 while (!isEmpty(stack1)) { Node* node = pop(stack1); // 如果当前节点有右子节点未访问,将它压入第一个栈 if (node->right) { push(stack1, node->right); } else { // 现在处理左子,将其余所有节点依次从第一个栈弹出并压入第二个栈 Node* temp = node; while (!isEmpty(stack1) && temp->left == NULL) { temp = pop(stack1); push(stack2, temp); } // 最后将根节点(非空)放入第二个栈,以便于最后访问 push(stack2, temp); } } // 从第二个栈中依次弹出并打印节点 while (!isEmpty(stack2)) print(pop(stack2)->data); } // 辅助函数,将节点及其子节点压入两个栈 Node* pushAndPop(Node* node, Stack* stack1, Stack* stack2) { push(stack1, node); if (node->left != NULL) { pushAndPop(node->left, stack1, stack2); } if (node->right != NULL) { pushAndPop(node->right, stack1, stack2); } return pop(stack2); } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值