其中包含有先序遍历、中序遍历、后序遍历以及广度优先遍历四种遍历树的方法:

 package com.ietree.basic.datastructure.tree.binarytree;

 import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue; /**
* Created by ietree
* 2017/5/1
*/
public class ThreeLinkBinTree<E> { 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;
} } private TreeNode root; // 以默认的构造器创建二叉树
public ThreeLinkBinTree() {
this.root = new TreeNode();
} // 以指定根元素创建二叉树
public ThreeLinkBinTree(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(parent + "节点为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) {
// 让父节点的left引用指向新节点
parent.left = newNode;
} else {
// 让父节点的left引用指向新节点
parent.right = newNode;
}
// 让新节点的parent引用到parent节点
newNode.parent = parent;
return newNode;
} // 判断二叉树是否为空
public boolean empty() {
// 根据元素判断二叉树是否为空
return root.data == null;
} // 返回根节点
public TreeNode root() {
if (empty()) {
throw new RuntimeException("树为空,无法访问根节点");
}
return root;
} // 返回指定节点(非根节点)的父节点
public E parent(TreeNode node) {
if (node == null) {
throw new RuntimeException("节点为null,无法访问其父节点");
}
return (E) node.parent.data;
} // 返回指定节点(非叶子)的左子节点,当左子节点不存在时返回null
public E leftChild(TreeNode parent) {
if (parent == null) {
throw new RuntimeException(parent + "节点为null,无法添加子节点");
}
return parent.left == null ? null : (E) parent.left.data;
} // 返回指定节点(非叶子)的右子节点,当右子节点不存在时返回null
public E rightChild(TreeNode parent) {
if (parent == null) {
throw new RuntimeException(parent + "节点为null,无法添加子节点");
}
return parent.right == null ? null : (E) parent.right.data;
} // 返回该二叉树的深度
public int deep() {
// 获取该树的深度
return deep(root);
} // 这是一个递归方法:每一棵子树的深度为其所有子树的最大深度 + 1
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;
// 返回其左右子树中较大的深度 + 1
return max + 1;
}
} // 实现先序遍历
// 1、访问根节点
// 2、递归遍历左子树
// 3、递归遍历右子树
public List<TreeNode> preIterator() {
return preIterator(root);
} private List<TreeNode> preIterator(TreeNode node) { List<TreeNode> list = new ArrayList<TreeNode>();
// 处理根节点
list.add(node); // 递归处理左子树
if (node.left != null) {
list.addAll(preIterator(node.left));
} // 递归处理右子树
if (node.right != null) {
list.addAll(preIterator(node.right));
} return list; } // 实现中序遍历
// 1、递归遍历左子树
// 2、访问根节点
// 3、递归遍历右子树
public List<TreeNode> inIterator() {
return inIterator(root);
} private List<TreeNode> inIterator(TreeNode node) { List<TreeNode> list = new ArrayList<TreeNode>(); // 递归处理左子树
if (node.left != null) {
list.addAll(inIterator(node.left));
} // 处理根节点
list.add(node); // 递归处理右子树
if (node.right != null) {
list.addAll(inIterator(node.right));
} return list; } // 实现后序遍历
// 1、递归遍历左子树
// 2、递归遍历右子树
// 3、访问根节点
public List<TreeNode> postIterator() {
return postIterator(root);
} private List<TreeNode> postIterator(TreeNode node) { List<TreeNode> list = new ArrayList<TreeNode>(); // 递归处理左子树
if (node.left != null) {
list.addAll(postIterator(node.left));
} // 递归处理右子树
if (node.right != null) {
list.addAll(postIterator(node.right));
} // 处理根节点
list.add(node); return list; } // 实现广度优先遍历
// 广度优先遍历又称为按层遍历,整个遍历算法先遍历二叉树的第一层(根节点),再遍历根节点的两个子节点(第二层),以此类推
public List<TreeNode> breadthFirst() { Queue<TreeNode> queue = new ArrayDeque<TreeNode>();
List<TreeNode> list = new ArrayList<TreeNode>();
if (root != null) {
// 将根元素加入“队列”
queue.offer(root);
}
while (!queue.isEmpty()) {
// 将该队列的“队尾”的元素添加到List中
list.add(queue.peek());
TreeNode p = queue.poll();
// 如果左子节点不为null,将它加入“队列”
if (p.left != null) {
queue.offer(p.left);
}
// 如果右子节点不为null,将它加入“队列”
if (p.right != null) {
queue.offer(p.right);
}
}
return list;
} }

Java中树和树的几种常规遍历方法的更多相关文章

  1. Java中获取键盘输入值的三种方法

    Java中获取键盘输入值的三种方法     Java程序开发过程中,需要从键盘获取输入值是常有的事,但Java它偏偏就没有像c语言给我们提供的scanf(),C++给我们提供的cin()获取键盘输入值 ...

  2. Java中从控制台输入数据的几种常用方法

    Java中从控制台输入数据的几种常用方法 一.使用标准输入串System.in //System.in.read()一次只读入一个字节数据,而我们通常要取得一个字符串或一组数字 //System.in ...

  3. Java中的ReentrantLock和synchronized两种锁定机制的对比

    问题:多个访问线程将需要写入到文件中的数据先保存到一个队列里面,然后由专门的 写出线程负责从队列中取出数据并写入到文件中. http://blog.csdn.net/top_code/article/ ...

  4. Java 集合 ArrayList和LinkedList的几种循环遍历方式及性能对比分析 [ 转载 ]

    Java 集合 ArrayList和LinkedList的几种循环遍历方式及性能对比分析 @author Trinea 原文链接:http://www.trinea.cn/android/arrayl ...

  5. JavaScript 中的12种循环遍历方法

    原文:JavaScript 中的12种循环遍历方法 题目:请介绍 JavaScript 中有哪些循环和遍历的方法,说说它们的应用场景和优缺点? 1.for 循环 let arr = [1,2,3];f ...

  6. java中调用dll文件的两种方法

    一中是用JNA方法,另外是用JNative方法,两种都是转载来的, JNA地址:http://blog.csdn.net/shendl/article/details/3589676   JNativ ...

  7. 【转】Java中super和this的几种用法与区别

    1. 子类的构造函数如果要引用super的话,必须把super放在函数的首位.   class Base {   Base() {   System.out.println("Base&qu ...

  8. Java中的内存泄露的几种可能

    Java内存泄漏引起的原因: 内存泄漏是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成内存空间的浪费称为内存泄漏. 长生命周期的对象持有短生命周期对象的引用就很可能发 ...

  9. Java中创建实例化对象的几种方式

    Java中创建实例化对象有哪些方式? ①最常见的创建对象方法,使用new语句创建一个对象.②通过工厂方法返回对象,例:String s =String.valueOf().(工厂方法涉及到框架)③动用 ...

随机推荐

  1. mysql实现经纬度计算两个坐标之间的距离

    DELIMITER $$CREATE DEFINER = CURRENT_USER FUNCTION `getDistance`(`lon1` float,`lat1` float,`lon2` fl ...

  2. 在Servlet处理请求的方式为。(选择1项)

    A.以进程的方式 B.以程序的方式 C.以线程的方式 D.以响应的方式 解答:C

  3. 故如果要比较两个字符串是否相同可以对a调用equal

    故如果要比较两个字符串是否相同(而不是他们的地址是否相同).可以对a调用equal: System.out.println(a.equal(b)); equal用来比较两个对象中字符串的顺序. a.e ...

  4. 【代码备份】NLM插值

    文件路径: main.m: %% 测试函数 clc,clear all,close all; %输入的原始小图 ima_ori=double(imread('F:\Users\****n\Docume ...

  5. hdu 3085(双向bfs)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3085 思路:双向广搜,每次从M出发,搜三步,从G出发,搜一步,然后就是判断是否走到对方已经走过的格子, ...

  6. leetcode 153: Majority Element

    Given an array of size n, find the majority element. The majority element is the element that appear ...

  7. MySQL中关于SQL注入的相关需要的基础知识

    零.绪论: 文章部分整理来源于公司同事,特此鸣谢!!! 一.关于注入点在KEY上的注入: 我们来看一个查询,你的第一个字段是过滤器(filter)第二个字段是查询的关键字,例如查询ip == 1.2. ...

  8. 【BZOJ4295】[PA2015]Hazard 乱搞

    [BZOJ4295][PA2015]Hazard Description 有n个人在轮流玩赌博机,一开始编号为i的人有a[i]元钱.赌博机可以抽象为一个长度为m的仅包含1和-1的序列,若抽到1,那么你 ...

  9. PHP HTTP协议(报头/状态码/缓存)

    一.HTTP协议介绍 1. #HTTP协议       # (1 建立在TCP/IP协议基础上       # (2 web开发数据传输依赖于http协议       # (3 http 协议全称是文 ...

  10. Caused by: java.sql.SQLException: Failed to start database 'metastore_db' with class loader org.apache.spark.sql.hive.client.IsolatedClientLoader$$anon$1@d7c365, see the next exception for details.

    解决方法:https://stackoverflow.com/questions/37442910/spark-shell-startup-errors 异常: 18/01/29 19:04:27 W ...