二叉树

1. 二叉树简介

定义: 每一个结点的子节点数量不超过 2

二叉树的结点分为:左节点、右节点

满二叉树: 每个结点都有两个子结点的二叉树(除了叶子结点外)

完全二叉树: 除去最后一层,是一个满二叉树,并且最后一层结点左连续

(从左到右,从上到下,依次编号1,2,3,4…,这样的编号和满二叉树一一对应的二叉树叫完全二叉树)

2. 链式存储的二叉树

2.1 创建二叉树

思路: 首先必须有一个BinaryTree 二叉树的类-用于设置根节点(也可以是一颗空树)

​ 其次需要结点 TreeNode 来构建二叉树

​ 结点包含:value结点值、leftNode左节点、rightNode右节点 以及设置/获取左右节点的方法

创建一个如下图的二叉树


具体化以后:

代码:

//二叉树
public class BinaryTree {//根节点TreeNode root;//设置根节点、获取根节点public TreeNode getRoot() {return root;}public void setRoot(TreeNode root) {this.root = root;}
}
//树的结点
public class TreeNode {//结点的值int value;//左节点TreeNode leftNode;//右节点TreeNode rightNode;//初始化值public TreeNode(int value){this.value=value;}//设置左节点public void setLeftNode(TreeNode leftNode) {this.leftNode = leftNode;}//设置右节点public void setRightNode(TreeNode rightNode) {this.rightNode = rightNode;}
}

测试类:

public class TestBinaryTree {public static void main(String[] args) {//创建一颗空二叉树BinaryTree binaryTree = new BinaryTree();//创建根结点TreeNode root=new TreeNode(1);binaryTree.setRoot(root);//创建根结点的左节点和右节点TreeNode leftNode = new TreeNode(2);TreeNode RightNode = new TreeNode(3);//将左右结点连接在根结点后root.setLeftNode(leftNode);root.setRightNode(RightNode);}
}

2.2 遍历二叉树

三种遍历方式: 前序遍历、中序遍历、后续遍历

(这里的前中后,都是对于当前结点而言)

前序遍历-当前结点在左右结点的前面:简记为 “根左右”

中序遍历-当前结点在左右结点的中间-“左根右”

后序遍历-当前结点在左右结点的后面-“左右根”

举个栗子:

前序遍历:1 2 4 5 3 6 7

中序遍历:4 2 5 1 6 3 7

后序遍历:4 5 2 6 7 3 1

代码实现:

TreeNode.java 中 (代码没有前部写出,前面已经写过的代码略)

    //前序遍历public void frontShow(){//遍历当前节点System.out.print(value+" ");//遍历左节点if(leftNode!=null){leftNode.frontShow();}//遍历右节点if(rightNode!=null){rightNode.frontShow();}}//中序遍历public void midShow(){//遍历左子节点if(leftNode!=null){leftNode.midShow();}//遍历当前节点System.out.print(value+" ");//遍历右子节点if(rightNode!=null){rightNode.midShow();}}//后序遍历public void afterShow(){//遍历左子节点if(leftNode!=null){leftNode.afterShow();}//遍历右子节点if(rightNode!=null){rightNode.afterShow();}//遍历当前节点System.out.print(value+" ");}

BinaryTree中实现封装:

//前中后序遍历public void frontShow(){root.frontShow();}public void midShow(){root.midShow();}public void afterShow(){root.afterShow();}

测试:

public class TestBinaryTree {public static void main(String[] args) {//创建一颗空二叉树BinaryTree binaryTree = new BinaryTree();//创建根结点TreeNode root=new TreeNode(1);binaryTree.setRoot(root);//创建根结点的左节点和右节点TreeNode leftNode = new TreeNode(2);TreeNode rightNode = new TreeNode(3);//将左右结点连接在根结点后root.setLeftNode(leftNode);root.setRightNode(rightNode);//增加四个节点 4、5、6、7方便遍历leftNode.setLeftNode(new TreeNode(4));leftNode.setRightNode(new TreeNode(5));rightNode.setLeftNode(new TreeNode(6));rightNode.setRightNode(new TreeNode(7));//前序、中序、后序遍历System.out.print("前序遍历:");binaryTree.frontShow();System.out.print("\n中序遍历:");binaryTree.midShow();System.out.print("\n后序遍历:");binaryTree.afterShow();System.out.println();}
}

结果:

前序遍历:1 2 4 5 3 6 7
中序遍历:4 2 5 1 6 3 7
后序遍历:4 5 2 6 7 3 1

可以看到和我们上面分析的结果一模一样

2.3 二叉树结点的查找

三种查找方式:前序、中序、后序查找
和遍历差不多,不同的是传入一个要查找的值,并且返回目标结点

三种查找实现差不多,只是查找顺序不同

代码:

    //前序查找public TreeNode frontSearch(int value){//目标节点TreeNode target=null;//先查找当前结点,如果值相同直接返回if(this.value==value){return this;}//查找左子节点if(leftNode!=null){target = leftNode.frontSearch(value);//如果左子节点返回的值不为空,则找到,直接返回if(target!=null){return target;}}//查找右子节点if(rightNode!=null){target = rightNode.frontSearch(value);}//返回return target;}//中序查找public TreeNode midSearch(int value){//目标节点TreeNode target=null;//先查找左子节点if(leftNode!=null){target = leftNode.midSearch(value);//如果左子节点返回的值不为空,则找到,直接返回if(target!=null){return target;}}//再查找当前结点,如果值相同直接返回if(this.value==value){return this;}//最后查找右子节点if(rightNode!=null){target = rightNode.midSearch(value);}//返回return target;}//后序查找public TreeNode afterSearch(int value){//目标节点TreeNode target=null;//先查找左子节点if(leftNode!=null){target = leftNode.afterSearch(value);//如果左子节点返回的值不为空,则找到,直接返回if(target!=null){return target;}}//再查找右子节点if(rightNode!=null){target = rightNode.afterSearch(value);if(target!=null){return target;}}//最后查找当前结点,如果值相同直接返回if(this.value==value){target=this;}//返回return target;}

BinaryTree中实现封装:

//前中后序查找public TreeNode frontSearch(int value){return root.frontSearch(value);}public TreeNode midSearch(int value){return root.midSearch(value);}public TreeNode afterSearch(int value){return root.afterSearch(value);}

测试:

//查找
System.out.println(binaryTree.frontSearch(3)==rightNode);
System.out.println(binaryTree.midSearch(6));
System.out.println(binaryTree.afterSearch(7));

结果:

true
com.dong.DataStructrue.Day_06.TreeNode@1554909b
com.dong.DataStructrue.Day_06.TreeNode@6bf256fa

可以看到,无论用什么查找方式都可以找到树中有的结点

2.4 删除结点(子树)

思路: 想删除一个结点,可以让其父节点指向它的TreeNode为null即可

​ 当删除的不是叶子节点,相当于删除子树

注意: 以下的删除方法只适用于 结点值不重复时

代码:

BinaryTree

//删除结点(子树)public void delete(int value){if(root!=null){//如果根节点是要删除的结点直接删除if(root.value==value){root=null;}else{//递归root.delete(value);}}else{System.out.println("当前是一颗空树,无法删除!");}}

TreeNode:

//删除结点(子树)public void delete(int value) {//存储父节点TreeNode parentNode=this;//判断左子节点if(parentNode.leftNode!=null&&parentNode.leftNode.value==value){//删除parentNode.leftNode=null;return;}//判断右节点if(parentNode.rightNode!=null&&parentNode.rightNode.value==value){//删除parentNode.rightNode=null;return;}//将左节点作为父节点,递归删除parentNode=leftNode;if(parentNode!=null){parentNode.delete(value);}//将右节点作为父节点,递归删除parentNode=rightNode;if(parentNode!=null){parentNode.delete(value);}}

测试:

//删除结点
System.out.print("删除前:");
binaryTree.frontShow();
System.out.println();
//这里4、7都是删除两个叶子结点
System.out.print("删除4:");
binaryTree.delete(4);
binaryTree.frontShow();
System.out.println();System.out.print("删除7:");
binaryTree.delete(7);
binaryTree.frontShow();
System.out.println();
//这里相当于删除了子树
System.out.print("删除2:");
binaryTree.delete(2);
binaryTree.frontShow();

结果:

删除前: 1 2 4 5 3 6 7
删除4: 1 2 5 3 6 7
删除7: 1 2 5 3 6
删除2: 1 3 6

3. 顺序存储的二叉树

思路:使用数组来存储,通过数组下标关系来找到左节点和右节点以及父节点,从而实现顺序存储二叉树

代码:

public class ArrayBinaryTree {//存储数据int[] data;public ArrayBinaryTree(int[] data) {this.data = data;}//不传参数,默认从0开始遍历public void frontShow(){frontShow(0);}//前序遍历,传入参数-从哪个下标开始遍历public void frontShow(int index){//当数据为空时if(data.length==0||data==null){System.out.print("当前为空树");return;}System.out.print(data[index]+" ");//遍历左节点=index*2+1if(index*2+1<data.length){frontShow(index*2+1);}//遍历右节点=index*2+2if(index*2+2<data.length){frontShow(index*2+2);}}
}

测试:

public class TestArrayBinaryTree {public static void main(String[] args) {//创建数组,传入值int[] data=new int[]{1,2,3,4,5,6,7};ArrayBinaryTree arrayBinaryTree = new ArrayBinaryTree(data);//前序遍历,从0开始System.out.print("前序遍历:");arrayBinaryTree.frontShow();}
}

结果:

前序遍历: 1 2 4 5 3 6 7

【二叉树详解】二叉树的创建、遍历、查找以及删除等-数据结构05相关推荐

  1. 【ZZ】详解哈希表的查找

    详解哈希表的查找 https://mp.weixin.qq.com/s/j2j9gS62L-mmOH4p89OTKQ 详解哈希表的查找 2018-03-01 算法与数据结构 来自:静默虚空 http: ...

  2. 详解二叉树的三种遍历方式(递归、迭代、Morris算法)

    详解二叉树的三种遍历方式(递归.迭代.Morris算法) 最重要的事情写在前面:遍历顺序不一定就是操作顺序!!! 递归解法 首先,一颗二叉树它的递归序列是一定的,导致其前中后序不同的原因只不过是访问节 ...

  3. 线索二叉树详解(C语言版)

    文章目录 一.定义 二.结构 三.常用操作 结语 附录 一.定义 前面学习了二叉树,在操作过程中发现了几个问题: 问题一:二叉树如何才能实现从一个指定结点开始遍历呢?         问题二:在二叉树 ...

  4. “iOS 推送通知”详解:从创建到设置到运行

    "iOS 推送通知"详解:从创建到设置到运行 转自 http://www.csdn.net/article/2012-02-18/311976 这是一篇编译的文章,内容均出自Par ...

  5. CSS3新特性详解(二):CSS3 字体@font-face详解、如何创建和修改woff字体文件及text-shadow等文本效果

      关于CSS3新特性,在上篇博文中"CSS3新特性详解(一):CSS3选择器.边框.背景使用细节及案例演示",讨论了CSS3选择器.边框和背景,本文讨论字体@font-face使 ...

  6. 数据结构-二叉树-详解

    目录 一.树的概念及结构 1.1树的概念 1.2 树的相关概念​ 1.3树的表示 1.4树在实际中的运用(表示文件系统的目录树结构) 二. 二叉树的概念及结构 2.1概念 2.2特殊二叉树 2.3二叉 ...

  7. 【线索二叉树详解】数据结构06(java实现)

    线索二叉树 1. 线索二叉树简介 定义: 在二叉树的结点上加上线索的二叉树称为线索二叉树. 二叉树的线索化: 对二叉树以某种遍历方式(如先序.中序.后序或层次等)进行遍历,使其变为线索二叉树的过程称为 ...

  8. 万字长文详解二叉树算法,再也不怕面试了!| 技术头条

    作者 | 人魔七七 责编 | 胡巍巍 树的基本概念篇 前言 由于我们后面讲的一些结构有很多是树结构实现的比如堆,然后基于堆可以实现优先级队列,有界优先级队列等,所以我们先讲述树结构,我们可能常见到的是 ...

  9. 常用算法(冒泡、插入、选择、快速)和二叉树详解

    同一问题可用不同算法解决,而一个算法的质量优劣将影响到算法乃至程序的效率.算法分析的目的在于选择合适算法和改进算法. 计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间.这是一个关 ...

最新文章

  1. ant design select 坑总结
  2. 分布式系统——向zabbix中添加监控项, 以nginx和mysql为例
  3. big sur 降级_太阳报:若诺维奇降级,球员将降薪一半
  4. C语言中的各输出格式含义
  5. InfoVista.NET 内部数据格式简介
  6. docker安装linux安装mysql_怎么启动mysql-linux 怎么安装mysql?怎么在docker搭建mysql8?docker安装mysql...
  7. mysql 表自动复制_mysql-10临时表、复制表
  8. 【POJ1101OpenJudge2802】The Game 小游戏(BFS+记忆化)
  9. 【BZOJ1057】[ZJOI2007] 棋盘制作(单调栈的运用)
  10. 如何设计一种简单的恒流/恒压降压转换器
  11. ShxViewer_SHX字体查看
  12. Centos7安装java运行环境
  13. 索尼相机手机控制对焦,操控指南丨 使用索尼微单的十个小技巧
  14. 360怎样修改wifi服务器,360路由器怎么设置无线网络
  15. 微服务架构与开源框架
  16. CET-4 week7 融会贯通
  17. vs2013 应用程序无法正常启动
  18. yum clean all的作用
  19. 转载于烂泥博客,供个人学习kvm、mysql等知识
  20. 计算机网络(一):计算机网络概念、功能、组成

热门文章

  1. python 数据分析学习笔记 (第三章)
  2. js动态载入css文件,原生JS动态加载JS、CSS文件及代码脚本(示例代码)
  3. Ubuntu18.04下安装MySQL
  4. 开启大数据时代谷歌三篇论文-Mapreduce
  5. 李宏毅线性代数笔记3:行列式det
  6. R语言实战应用精讲50篇(十一)-单因素方差分析 | 事后两两多重比较 | 趋势方差分析
  7. Matplotlib实例教程(十一)堆栈图
  8. SpringBoot Whitelabel Error Page的根本原因,三种解决方案以及其特点
  9. 阿里云、Amazon、Google云数据库方案架构与技术分析
  10. CORS support in Spring Framework--官方