【数据结构】之二叉树(Java语言描述)
有关树的一些基础知识点请参考【这篇文章】。
本文主要记录Java语言描述的二叉树相关的一些操作,如创建、遍历等。
首先,我们需要一个表示树中节点的数据结构TreeNode,代码如下:
public class TreeNode<T> {
public T data;
public TreeNode<T> lChild;
public TreeNode<T> rChild;
public TreeNode<T> parent;
public TreeNode() {
}
public TreeNode(T data) {
this.data = data;
this.lChild = null;
this.rChild = null;
this.parent = null;
}
public TreeNode(T data, TreeNode<T> parent, boolean isLeftC) {
this.data = data;
this.parent = parent;
if (isLeftC) {
parent.lChild = this;
} else {
parent.rChild = this;
}
}
}
在二叉树的工具类BinaryTree中,提供了很多的方法,详细介绍如下:
(1)创建二叉树的时候,通过传入的字符串来自动生成二叉树的结构。注意:字符串是前序遍历的结构,每个节点都有左右两个节点,如果某个节点为空,则用“#”符号表示;节点与节点之间用空格隔开。
(2)使用递归和非递归的方式进行二叉树的前、中、后序遍历的方法。
(3)对二叉树进行层序遍历的方法。
(4)获取树的深度和树中节点总数的方法。
以下是BinaryTree类中的详细代码:
public class BinaryTree {
private TreeNode<String> root;
private int size;
// 根据初始化字符串生成二叉树
public BinaryTree(String content) {
root = createBTree(new Scanner(content));
}
// 直接将一棵TreeNode树赋值为二叉树
public BinaryTree(TreeNode<String> root) {
this.root = root;
}
// 根据字符串创建二叉树
private TreeNode<String> createBTree(Scanner scanner) {
String data = scanner.next();
if ("#".equals(data)) return null;
TreeNode<String> node = new TreeNode<>(data);
size++;
node.lChild = createBTree(scanner);
node.rChild = createBTree(scanner);
return node;
}
// 获取二叉树的深度
public int getBTreeDepth() {
return getBTreeDepth(root);
}
private int getBTreeDepth(TreeNode root) {
return root == null ? 0 : Math.max(getBTreeDepth(root.lChild), getBTreeDepth(root.rChild)) + 1;
}
// 返回二叉树中节点个数
public int size() {
return size;
}
// 前序遍历二叉树(useRec:是否使用递归方式)
public void traverseBefore(boolean useRec) {
if (useRec) {
traverseBeforeRec(root);
} else {
traverseBeforeNonRec();
}
}
// 前序遍历二叉树(递归)
private void traverseBeforeRec(TreeNode node) {
if (node == null) {
System.out.print("#");
} else {
System.out.print(node.data);
traverseBeforeRec(node.lChild);
traverseBeforeRec(node.rChild);
}
}
// 前序遍历二叉树(非递归)
private void traverseBeforeNonRec() {
Stack<TreeNode<String>> stack = new Stack<>();
TreeNode<String> currRoot = root;
while (true) {
if (currRoot != null) {
System.out.print(currRoot.data);
stack.push(currRoot.rChild);
currRoot = currRoot.lChild;
} else {
System.out.print("#");
if (stack.size() == 0) break;
currRoot = stack.pop();
}
}
}
// 中序遍历二叉树
public void traverseMiddle(boolean useRec) {
if (useRec) {
traverseMiddleRec(root);
} else {
traverseMiddleNonRec();
}
}
// 中序遍历二叉树(递归)
private void traverseMiddleRec(TreeNode node) {
if (node == null) {
System.out.print("#");
} else {
traverseMiddleRec(node.lChild);
System.out.print(node.data);
traverseMiddleRec(node.rChild);
}
}
// 中序遍历二叉树(非递归)
private void traverseMiddleNonRec() {
Stack<TreeNode<String>> stack = new Stack<>();
TreeNode<String> currRoot = root;
while (true) {
if (currRoot != null) {
stack.push(currRoot);
currRoot = currRoot.lChild;
} else {
System.out.print("#");
if (stack.size() == 0) break;
TreeNode<String> middleNode = stack.pop();
System.out.print(middleNode.data);
currRoot = middleNode.rChild;
}
}
}
// 后序遍历二叉树
public void traverseAfter(boolean useRec) {
if (useRec) {
traverseAfterRec(root);
} else {
traverseAfterNonRec();
}
}
// 后序遍历二叉树(递归)
private void traverseAfterRec(TreeNode node) {
if (node == null) {
System.out.print("#");
} else {
traverseAfterRec(node.lChild);
traverseAfterRec(node.rChild);
System.out.print(node.data);
}
}
// 后序遍历二叉树(非递归)
private void traverseAfterNonRec() {
Stack<TreeNode<String>> stack = new Stack<>();
TreeNode<String> lastNode = null;
TreeNode<String> currRoot = root;
while (true) {
if (currRoot != null) {
if (lastNode != null && currRoot.rChild == lastNode) {
System.out.print(currRoot.data);
lastNode = currRoot;
currRoot = stack.peek().rChild;
if (root.rChild == currRoot && currRoot == lastNode) {
System.out.print(root.data);
break;
}
} else if (lastNode != null && currRoot.lChild == lastNode) {
if (currRoot.rChild == null) {
System.out.print("#" + currRoot.data);
lastNode = currRoot;
currRoot = stack.pop();
}
} else {
stack.push(currRoot);
currRoot = currRoot.lChild;
}
} else {
System.out.print("#");
currRoot = stack.peek().rChild;
if (currRoot == null) {
System.out.print("#");
lastNode = stack.pop();
System.out.print(lastNode.data);
currRoot = stack.pop();
}
}
}
}
// 层序遍历二叉树
public void traverseCeng() {
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
if (node == null) {
System.out.print("#");
} else {
System.out.print(node.data);
queue.offer(node.lChild);
queue.offer(node.rChild);
}
}
}
}
测试类代码:
public class TestTree {
private static final String TREE_CONTENT = "A B D # G # # E # # C # F H # # #";
public static void main(String args[]) {
System.out.println("根据字符串" + TREE_CONTENT + "生成二叉树");
BinaryTree bTree = new BinaryTree(TREE_CONTENT);
System.out.print("二叉树前序遍历结果:");
bTree.traverseBefore(false);
System.out.print("\n二叉树中序遍历结果:");
bTree.traverseMiddle(false);
System.out.print("\n二叉树后序遍历结果:");
bTree.traverseAfter(false);
System.out.print("\n二叉树层序遍历结果:");
bTree.traverseCeng();
System.out.println("\n二叉树深度:" + bTree.getBTreeDepth());
System.out.println("二叉树中节点个数:" + bTree.size());
}
}
运行结果:
根据字符串A B D # G # # E # # C # F H # # #生成二叉树
二叉树前序遍历结果:ABD#G##E##C#FH###
二叉树中序遍历结果:#D#G#B#E#A#C#H#F#
二叉树后序遍历结果:###G##E###HFC
二叉树层序遍历结果:ABCDE#F#G##H#####
二叉树深度:4
二叉树中节点个数:8
【数据结构】之二叉树(Java语言描述)的更多相关文章
- 数据结构与抽象 Java语言描述 第4版 pdf (内含标签)
数据结构与抽象 Java语言描述 第4版 目录 前言引言组织数据序言设计类P.1封装P.2说明方法P.2.1注释P.2.2前置条件和后置条件P.2.3断言P.3Java接口P.3.1写一个接口P.3. ...
- 《数据结构与算法分析-Java语言描述》 分享下载
书籍信息 书名:<数据结构与算法分析-Java语言描述> 原作名:Data Structures and Algorithm Analysis in Java 作者: 韦斯 (Mark A ...
- 读书笔记:《数据结构与算法分析Java语言描述》
目录 第 3 章 表.栈和队列 3.2 表 ADT 3.2.1 表的简单数组实现 3.2.2 简单链表 3.3 Java Collections API 中的表 3.3.1 Collection 接口 ...
- 数据结构(java语言描述)
概念性描述与<数据结构实例教程>大同小异,具体参考:http://www.cnblogs.com/bookwed/p/6763300.html. 概述 基本概念及术语 数据 信息的载体,是 ...
- 数据结构(Java语言描述)-第一章:概述
第一章 概述 1.0 序言 自己为啥要学数据结构嘞,我觉得主要有以下三个原因: 前段时间在看并发编程时,发现aqs,corrunthashmap等底层都用到了数据结构,主要的有队列,还有链表,学习数据 ...
- C语言学习书籍推荐《数据结构与算法分析:C语言描述(原书第2版)》下载
维斯 (作者), 冯舜玺 (译者) <数据结构与算法分析:C语言描述(原书第2版)>内容简介:书中详细介绍了当前流行的论题和新的变化,讨论了算法设计技巧,并在研究算法的性能.效率以及对运行 ...
- 数据结构与算法分析——C语言描述 第三章的单链表
数据结构与算法分析--C语言描述 第三章的单链表 很基础的东西.走一遍流程.有人说学编程最简单最笨的方法就是把书上的代码敲一遍.这个我是头文件是照抄的..c源文件自己实现. list.h typede ...
- 三元组表压缩存储稀疏矩阵实现稀疏矩阵的快速转置(Java语言描述)
三元组表压缩存储稀疏矩阵实现稀疏矩阵的快速转置(Java语言描述) 用经典矩阵转置算法和普通的三元组矩阵转置在时间复杂度上都是不乐观的.快速转置算法在增加适当存储空间后实现快速转置具体原理见代码注释部 ...
- 利用栈实现算术表达式求值(Java语言描述)
利用栈实现算术表达式求值(Java语言描述) 算术表达式求值是栈的典型应用,自己写栈,实现Java栈算术表达式求值,涉及栈,编译原理方面的知识.声明:部分代码参考自茫茫大海的专栏. 链栈的实现: pa ...
随机推荐
- Security整合spring boot
Security整合spring boot 1.基础概念 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spri ...
- 2019 年容器生态统计报告发布 | 云原生生态周报 Vol. 26
作者 | 酒祝.天元.元毅.心水.衷源 业界要闻 1.2019 年容器生态统计报告发布 据报告显示,Kubernetes 占据 77% 的容器编排产品份额,Docker 占据 79% 的容器引擎产品 ...
- 运用wxs制作微信小程序左滑功能和跳转,性能更优越
锲子 微信小程序自定义左滑功能加上跳转,换成以往,左滑功能的逻辑一般是在js中实现,但在拖动方面,性能并不是那么的流畅.如今,官方新扩展了一套脚本语言wxs,在IOS设备上运行,性能会比JS快2~20 ...
- 一道国外前端面试题引发的Coding...
刚刚看到CSDN微信公众号一篇文章,关于国外程序员面试前端遇到的一道测试题,有点意思,遂写了下代码,并记录一下~ 题目是这样的: ['Tokyo', 'London', 'Rome', 'Donlon ...
- [考试反思]0719NOIP模拟测试6 + 0722NOIP模拟测试7
连续爆炸,颇为愉快. 第6次:Rank #4 第7次:Rank #9 对于第6次考试,个人比较满意,因为T1只是差了一个卡常. 因为在考试前两天刚讲了矩阵,满脑子都是矩阵,还想到了循环矩阵优化. 整个 ...
- Mybaits 源码解析 (十)----- 全网最详细,没有之一:Spring-Mybatis框架使用与源码解析
在前面几篇文章中我们主要分析了Mybatis的单独使用,在实际在常规项目开发中,大部分都会使用mybatis与Spring结合起来使用,毕竟现在不用Spring开发的项目实在太少了.本篇文章便来介绍下 ...
- elasticsearch操作命令
总结几个es的curl操作命令: 查询某条数据:curl -XGET http://elasticsearch:9200/company/company/123?pretty 查询索引下数据总量:cu ...
- 洛谷 P 5 3 0 4 [GXOI/GZOI2019]旅行者
题目描述 J 国有 n 座城市,这些城市之间通过 m 条单向道路相连,已知每条道路的长度. 一次,居住在 J 国的 Rainbow 邀请 Vani 来作客.不过,作为一名资深的旅行者,Vani 只对 ...
- 前端Vue中常用rules校验规则
前提 在 vue开发中,难免遇到各种表单校验,这里整理了网络上和自己平时高频率用到的一些校验方法.如果错误欢迎指出,后期不断补充更新. 1.是否合法IP地址 export function valid ...
- Microsoft Visual C++ 14.0 is required问题解决
当我们在windows下安装包或者软件时会出现: Microsoft Visual C++ b'v14.0 is required 错误解决办法 直接下载安装visualstudio: https:/ ...