有关树的一些基础知识点请参考【这篇文章】。

  本文主要记录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语言描述)的更多相关文章

  1. 数据结构与抽象 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. ...

  2. 《数据结构与算法分析-Java语言描述》 分享下载

    书籍信息 书名:<数据结构与算法分析-Java语言描述> 原作名:Data Structures and Algorithm Analysis in Java 作者: 韦斯 (Mark A ...

  3. 读书笔记:《数据结构与算法分析Java语言描述》

    目录 第 3 章 表.栈和队列 3.2 表 ADT 3.2.1 表的简单数组实现 3.2.2 简单链表 3.3 Java Collections API 中的表 3.3.1 Collection 接口 ...

  4. 数据结构(java语言描述)

    概念性描述与<数据结构实例教程>大同小异,具体参考:http://www.cnblogs.com/bookwed/p/6763300.html. 概述 基本概念及术语 数据 信息的载体,是 ...

  5. 数据结构(Java语言描述)-第一章:概述

    第一章 概述 1.0 序言 自己为啥要学数据结构嘞,我觉得主要有以下三个原因: 前段时间在看并发编程时,发现aqs,corrunthashmap等底层都用到了数据结构,主要的有队列,还有链表,学习数据 ...

  6. C语言学习书籍推荐《数据结构与算法分析:C语言描述(原书第2版)》下载

    维斯 (作者), 冯舜玺 (译者) <数据结构与算法分析:C语言描述(原书第2版)>内容简介:书中详细介绍了当前流行的论题和新的变化,讨论了算法设计技巧,并在研究算法的性能.效率以及对运行 ...

  7. 数据结构与算法分析——C语言描述 第三章的单链表

    数据结构与算法分析--C语言描述 第三章的单链表 很基础的东西.走一遍流程.有人说学编程最简单最笨的方法就是把书上的代码敲一遍.这个我是头文件是照抄的..c源文件自己实现. list.h typede ...

  8. 三元组表压缩存储稀疏矩阵实现稀疏矩阵的快速转置(Java语言描述)

    三元组表压缩存储稀疏矩阵实现稀疏矩阵的快速转置(Java语言描述) 用经典矩阵转置算法和普通的三元组矩阵转置在时间复杂度上都是不乐观的.快速转置算法在增加适当存储空间后实现快速转置具体原理见代码注释部 ...

  9. 利用栈实现算术表达式求值(Java语言描述)

    利用栈实现算术表达式求值(Java语言描述) 算术表达式求值是栈的典型应用,自己写栈,实现Java栈算术表达式求值,涉及栈,编译原理方面的知识.声明:部分代码参考自茫茫大海的专栏. 链栈的实现: pa ...

随机推荐

  1. ManyToMany 字段的使用

    创建一个经典的多对多关系:一本书可以有多个作者,一个作者可以有多本书(如下,csdn复制的图片) 当进行数据迁移时,会生成三张表,了解就好 1,查询数据的操作 : 1.一本书的所有作者 b = Boo ...

  2. egg-mongoose --- nodejs

    项目 egg + mongoose 项目结构 配置 egg 安装模块 npm i egg-mongoose --save config/pulgin.js exports.mongoose = { e ...

  3. HTTP 304状态码的详细讲解

    首先,对于304状态码不应该认为是一种错误,而是对客户端有缓存情况下服务端的一种响应. 客户端在请求一个文件的时候,发现自己缓存的文件有 Last Modified ,那么在请求中会包含 If Mod ...

  4. 明解C语言 入门篇 第三章答案

    练习3-1 #include <stdio.h> int main() { int x; int y; puts("请输入两个整数."); printf("整 ...

  5. MAVEN(一) 安装和环境变量配置

    一.安装步骤 1.安装maven之前先安装jdk,并配置好环境变量.确保已安装JDK,并 “JAVA_HOME” 变量已加入到 Windows 环境变量. 2.下载maven 进入官方网站下载网址如下 ...

  6. Java 计算n对应的二进制位上有几个1,分别在什么位置

    Java计算n的二进制位上有几个1,分别在什么位置   public List<Integer> getBinOneCount(int n){     List<Integer> ...

  7. VS Code 1.40 发布!可自行搭建 Web 版 VS Code!

    今天(北京时间 2019 年 11 月 8 日),微软发布了 Visual Studio Code 1.40 版本.让我们来看看有哪些主要的更新. 自建 Web 版 VS Code 前不久,微软正式发 ...

  8. 建议收藏:.net core 使用导入导出Excel详细案例,精心整理源码已更新至开源模板

    还记得刚曾经因为导入导出不会做而发愁的自己吗?我见过自己前同事因为一个导出改了好几天,然后我们发现虽然有开源的库但是用起来却不得心应手,主要是因为百度使用方案的时候很多方案并不能解决问题. 尤其是尝试 ...

  9. 深度解密Go语言之 pprof

    目录 什么是 pprof pprof 的作用 pprof 如何使用 runtime/pprof net/http/pprof pprof 进阶 Russ Cox 实战 查找内存泄露 总结 参考资料 相 ...

  10. [考试反思]1105csp-s模拟测试101: 临别

    先不改题,这次主要不在T3上. 这次有必要粘文件得分了. 临考前总解锁新锅我也不知道这是什么个事啊... T1宏定义写挂.因为原来在OJ上没事所以一直没注意.在Lemon评测下直接全部RE. GG在主 ...