二叉树的遍历
来源:互联网 发布:域名隐藏ip地址 编辑:程序博客网 时间:2024/06/05 06:05
二叉树的遍历
先序遍历
所有父节点先于左右子树的顺序,父亲 -> 左子树(递归) -> 右子树(递归)
后续遍历
所有父节点后于左右子树的顺序, 左子树(递归) -> 右子树(递归) -> 父亲
中序遍历
父节点的在左右子树的中间访问,左子树(递归)-> 父亲 -> 右子树(递归)
层序遍历
借助一个双端队列实现,比如有如下的二叉树
将根节点加入队列
不断地取出队列中第一个元素加入list, 并将当前节点的的两个孩子加入队列 ,
循环直到队列为空,则遍历结束
最终遍历结果为list, 工具双端队列queue:
代码如下
package com.susq.algorithm.tree;import java.util.ArrayDeque;import java.util.ArrayList;import java.util.List;import java.util.Queue;/** * @author susq * @since 2017-12-14-14:56 */public class BinTree<E> { private TreeNode root; public BinTree() { this.root = new TreeNode(); } public BinTree(E data) { this.root = new TreeNode(data); } /** * 为指定节点添加新节点 * * @param parent 父节点 * @param data 新的数据 * @param isLeft 是否为左孩子 * @return 新的节点 */ public TreeNode addNode(TreeNode parent, E data, boolean isLeft) { if (parent == null) { throw new RuntimeException("节点为null, 无法添加子节点"); } if (isLeft && parent.left != null) { throw new RuntimeException(parent + "已经有左子节点,无法继续添加"); } if (!isLeft && parent.right != null) { throw new RuntimeException(parent + "已经有右子节点,无法继续添加"); } TreeNode newNode = new TreeNode(data); if (isLeft) { parent.left = newNode; } else { parent.right = newNode; } newNode.parent = parent; return newNode; } public boolean empty() { return root.data == null; } public TreeNode getRoot() { if (empty()) { throw new RuntimeException("树为空"); } return root; } public E parent(TreeNode node) { if (node == null) { throw new RuntimeException("节点为空,没有父节点"); } return (E) node.parent.data; } public E leftChild(TreeNode parent) { if (parent == null) { throw new RuntimeException("节点为空,没有孩子"); } return parent.left == null ? null : (E) parent.left; } public E rightChild(TreeNode parent) { if (parent == null) { throw new RuntimeException("节点为空,没有孩子"); } return parent.right == null ? null : (E) parent.right; } public int deep() { return deep(root); } private int deep(TreeNode node) { if (node == null) { return 0; } if (node.left == null && node.right == null) { return 1; } else { int leftDeep = deep(node.left); int rightDeep = deep(node.right); int max = leftDeep > rightDeep ? leftDeep : rightDeep; return max + 1; } } /** * 实现先序遍历 * * @return */ public List<TreeNode> preIterator() { return preIterator(root); } private List<TreeNode> preIterator(TreeNode node) { List<TreeNode> list = new ArrayList<>(); list.add(root); // 递归处理左子树 if (node.left != null) { list.addAll(preIterator(node.left)); } // 递归处理右子树 if (node.right != null) { list.addAll(preIterator(node.right)); } return list; } /** * 实现中序遍历 * * @return */ public List<TreeNode> inIterator() { return inIterator(root); } private List<TreeNode> inIterator(TreeNode node) { List<TreeNode> list = new ArrayList<>(); if (node.left != null) { list.addAll(inIterator(node.left)); } list.add(root); if (node.right != null) { list.addAll(inIterator(node.right)); } return list; } /** * 实现后续遍历 * * @return */ public List<TreeNode> psotIterator() { return postIterator(root); } private List<TreeNode> postIterator(TreeNode node) { List<TreeNode> list = new ArrayList<>(); if (node.left != null) { list.addAll(postIterator(node.left)); } if (node.right != null) { list.addAll(postIterator(node.right)); } list.add(root); return list; } /** * 实现广度优先遍历,又称为按层遍历 * 借助一个双端队列 * * @return */ public List<TreeNode> breadthFirst() { Queue<TreeNode> queue = new ArrayDeque<>(); //ArrayDeque数双端队列实现类 List<TreeNode> list = new ArrayList<>(); if (root != null) { queue.offer(root); // offer:添加一个元素并返回true,如果队列已满,则返回false } // while 循环中,移除队列的第一个节点,并且将这个节点左子节点、右子节点加入队列, // 每次取出队列中元素的时候,把它的所有孩子加入队列末尾,在二叉树中就是父节点遍历过后,把下层的节点加入队列。 while (!queue.isEmpty()) { list.add(queue.peek()); // peek:返回队列头部的元素,如果队列为空,则返回null TreeNode p = queue.poll(); //poll:移除并返问队列头部的元素, 如果队列为空,则返回null if (p.left != null) { queue.offer(p.left); } if (p.right != null) { queue.offer(p.right); } } return list; } /** * 树的节点 */ public static class TreeNode { Object data; TreeNode left; TreeNode right; TreeNode parent; public TreeNode() { } public TreeNode(Object data) { this.data = data; } public TreeNode(Object data, TreeNode left, TreeNode right, TreeNode parent) { this.data = data; this.left = left; this.right = right; this.parent = parent; } }}
阅读全文
0 0
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 几个硬盘接口协议IDE, PATA, ATA, SATA, SAS, SCSI,PCIe, FC的总结
- Hibernate 核心技术(二)
- SpringBoot Eclipse部署到tomcat
- 每天一个linux命令(24):Linux文件类型与扩展名
- 使用sublime text必备技巧
- 二叉树的遍历
- 216. Combination Sum III
- 如何通过路由器快速组建 VPN 网络
- Molog:使用 Serverless 搭建的前端错误日志及事件收集系统
- 汉诺塔问题
- 每天一个linux命令(25):linux文件属性详解
- DeepFashion: 服装公开数据集概述
- API接口说明
- 介绍Compiler的构造比较无趣,不如先过后面的,在用到compiler的时候再做讲解