【数据结构】之二叉树(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 ...
随机推荐
- else 的特殊用法和三目运算
1,eval() 获取原始数据类型 例1: str = " a = eval(str) print(a,type(a)) a得到的结果是整型10,不是字符串10 例2: str1 = &qu ...
- Bash 通配符、正则表达式、扩展正则表达式
BASH中的通配符(wildcard) *:任意长度的任意字符. ?:任意单个字符 []:匹配范围 [^]:排除匹配范围 [:alnum:]:所有字母和数字 [:alpha:]:所有字母 [:digi ...
- wfi破解
破解wifi步骤 1.准备字典(常见字典 数字组合.常用姓氏.汉字姓名+年份组合等等) 2.无线网卡 3.查看附近WiFi信息 前言 : 随着无线网络走进我们的生活,在方便了我们的同时又产生了许多的安 ...
- [考试反思]0807NOIP模拟测试14:承认
一大排并列Rank#9之一. 考试题还没改完(而且并不会模拟退火)所以题解又只能咕了 然而并不想吐槽T2对sjzyz是原题导致4个AC里面有3个他们的 虽说这次的成绩不怎么样,但是这次的考试过程是全新 ...
- 2019.11.11 洛谷月赛t3
题目背景 由于Y校的老师非常毒瘤,要求\(zhouwc\)在\(csp\)考前最后\(3\)天参加期中考,\(zhouwc\)非常生气,决定消极考试,以涂完卡但全错为目标.现在\(retcarizy\ ...
- 使用Typescript重构axios(十五)——默认配置
0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...
- ASP.NET Core 3.x 并发限制
前言 Microsoft.AspNetCore.ConcurrencyLimiter AspNetCore3.0后增加的,用于传入的请求进行排队处理,避免线程池的不足. 我们日常开发中可能常做的给某w ...
- [UWP]使用CompositionAPI的翻转动画
1. 运行效果 在 使用GetAlphaMask和ContainerVisual制作长阴影(Long Shadow) 这篇文章里我介绍了一个包含长阴影的番茄钟,这个番茄钟在状态切换时用到了翻转动画,效 ...
- Prometheus客户端开发:腾讯云CLB
一:简介 随着prometheus的使用人群逐渐扩大,官方定义的client exporter虽然能满足我们的大部分需求,但是很多监控还是需要我们自定义开发,以下内容就是基于腾讯云SDK,对腾讯云CL ...
- Webpack 4 Tree Shaking 终极优化指南
几个月前,我的任务是将我们组的 Vue.js 项目构建配置升级到 Webpack 4.我们的主要目标之一是利用 tree-shaking 的优势,即 Webpack 去掉了实际上并没有使用的代码来减少 ...