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

 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. heartbeat 心跳技术

    转自:http://blog.csdn.net/keda8997110/article/details/8349049 heartbeat 心跳技术原理: heartbeat (Linux-HA)的工 ...

  2. java----序列化与反序列化中及java序列化本质就是存储一个对象,然后在其他地方在调用它

    Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是 ...

  3. mysql插入多行数据

    表结构如图:

  4. python pycurl属性

    pycurl.Curl() #创建一个pycurl对象的方法 pycurl.Curl(pycurl.URL, http://www.google.com.hk) #设置要访问的URL pycurl.C ...

  5. 《Programming with Objective-C》第四章 Encapsulating Data

    Designated Initializer 不稳定的传送门 合成属性 Properties don’t always have to be backed by their own instance ...

  6. 编程之美 set 21 24点游戏

    题目 输入: n1, n2, n3, n4 (1~13) 输出: 若能得到运算结果为 24, 则输出一个对应的运算表达式 如: 输入: 11, 8, 3, 5 输出: (11-8) * (3*5) = ...

  7. java解析xml字符串(用dom4j)

    package com.smsServer.Dhst; import java.util.HashMap; import java.util.Iterator; import java.util.Ma ...

  8. PHPStorm自动压缩YUI Compressor配置

    File---Settings...---Tools---File Watchers 点击右边加号,添加: 在弹出窗中 主要是Program的内容,点击后面的省略点,默认目录下回出现yuicompre ...

  9. 安装dede UTF_8时报出了一个致命错误和警告,最后不能显示网站后台和首页了

    安装dede UTF_8时报出了一个致命错误和警告,最后不能显示网站后台和首页了.报错如下: 登陆首页显示:Fatal error: Call to undefined function ParCv( ...

  10. 关于ln(link)命令

    一. ln分为硬链接和软链接. 二. 硬链接命令为: ln test/a.text hard.text 1. 这样hard.text拥有 test目录下a.text相同的i节点(inode的id号)和 ...