zoukankan      html  css  js  c++  java
  • 二叉树

    为什么需要树这种数据结构

    1. 数组存储方式的分析
          
      优点:通过下标方式访问元素,速度快。对于有序数组,还可使用二分查找提高检索速度。
          
      缺点:如果要检索具体某个值,或者插入值(按一定顺序)会整体移动,效率较低 [示意图]
    2. 链式存储方式的分析
          
      优点:在一定程度上对数组存储方式有优化(比如:插入一个数值节点,只需要将插入节点,链接到链表中即可)
          
      缺点:在进行检索时,效率仍然较低,比如(检索某个值,需要从头节点开始遍历) 【示意图】
    3. 树存储方式的分析
          
      能提高数据存储,读取的效率, 比如利用二叉排序树(Binary Sort Tree),既可以保证数据的检索速度,同时也可以保证数据的插入,删除,修改的速度。

    二叉树的示意图

    1. 树的常用术语(结合示意图理解):

      1. 节点
      2. 根节点
      3. 父节点
      4. 子节点
      5. 叶子节点 (没有子节点的节点)
      6. 节点的权(节点值)
      7. 路径(root节点找到该节点的路线)
      8. 子树
      9. 树的高度(最大层数)
      10. 森林

    二叉树的概念

    1. 树有很多种,每个节点最多只能有两个子节点的一种形式称为二叉树。
    2. 二叉树的子节点分为左节点和右节点。

    3. 如果该二叉树的所有叶子节点都在最后一层,并且结点总数= 2^n -1 , n 为层数,则我们称为满二叉树。
    4. 如果该二叉树的所有叶子节点都在最后一层或者倒数第二层,而且最后一层的叶子节点在左边连续,倒数第二层的叶子节点在右边连续,我们称为完全二叉树。

    二叉树遍历的说明

    1. 使用前序,中序和后序对下面的二叉树进行遍历.

      对各种遍历方式的说明:

    • 前序遍历: 先输出父节点,再遍历左子树和右子树
    • 中序遍历: 先遍历左子树,再输出父节点,再遍历右子树
    • 后序遍历: 先遍历左子树,再遍历右子树,最后输出父节点
    • 小结: 看输出父节点的顺序,就确定是前序,中序还是后序

    二叉树遍历应用实例(前序,中序,后序)

    代码实现:

    package com.atguigu.chapter18.binarytree

     

    object BinaryTreeDemo {

    def main(args: Array[String]): Unit = {

     

    //先使用比较简单方法,直接关联的方法

    val root = new HeroNode(1,"宋江")

    val hero2 = new HeroNode(2,"吴用")

    val hero3 = new HeroNode(3,"卢俊义")

    val hero4 = new HeroNode(4,"林冲")

    val hero5 = new HeroNode(5,"关胜")

     

    root.left = hero2

    root.right = hero3

     

    hero3.left = hero5

    hero3.right = hero4

     

    val binaryTree = new BinaryTree

    binaryTree.root = root

     

    // println("前序遍历")

    // binaryTree.preOrder()

     

    // println("中序遍历")

    // binaryTree.infixOrder()

     

    println("后序遍历")

    binaryTree.postOrder()

    }

    }

     

    //定义节点

    class HeroNode(hNo: Int, hName: String) {

    val no = hNo

    var name = hName

    var left: HeroNode = null

    var right: HeroNode = null

     

    //后序遍历

    def postOrder(): Unit = {

    //向左递归输出左子树

    if (this.left != null) {

    this.left.postOrder()

    }

    //向右边递归输出右子树

    if (this.right != null) {

    this.right.postOrder()

    }

    //先输出当前节点值

    printf("节点信息 no=%d name=%s ",no,name)

    }

     

    //中序遍历

    def infixOrder(): Unit = {

    //向左递归输出左子树

    if (this.left != null) {

    this.left.infixOrder()

    }

    //先输出当前节点值

    printf("节点信息 no=%d name=%s ",no,name)

    //向右边递归输出右子树

    if (this.right != null) {

    this.right.infixOrder()

    }

     

    }

     

    //前序遍历

    def preOrder(): Unit = {

    //先输出当前节点值

    printf("节点信息 no=%d name=%s ",no,name)

    //向左递归输出左子树

    if (this.left != null) {

    this.left.preOrder()

    }

    //向右边递归输出右子树

    if (this.right != null) {

    this.right.preOrder()

    }

    }

    }

     

    class BinaryTree {

    var root: HeroNode = null

     

     

    //后序遍历

    def postOrder(): Unit = {

    if (root != null){

    root.postOrder()

    }else {

    println("当前二叉树为空,不能遍历")

    }

    }

     

    //中序遍历

    def infixOrder(): Unit = {

    if (root != null){

    root.infixOrder()

    }else {

    println("当前二叉树为空,不能遍历")

    }

    }

     

    //前序遍历

    def preOrder(): Unit = {

    if (root != null){

    root.preOrder()

    }else {

    println("当前二叉树为空,不能遍历")

    }

    }

    }

     

    二叉树-查找指定节点

    要求

    1. 请编写前序查找,中序查找和后序查找的方法。
    2. 并分别使用三种查找方式,查找 heroNO = 5 的节点
    3. 并分析各种查找方式,分别比较了多少
    4. 代码实现和思路分析

    package com.atguigu.chapter18.binarytree

     

    object BinaryTreeDemo {

    def main(args: Array[String]): Unit = {

     

    //先使用比较简单方法,直接关联的方法

    val root = new HeroNode(1,"宋江")

    val hero2 = new HeroNode(2,"吴用")

    val hero3 = new HeroNode(3,"卢俊义")

    val hero4 = new HeroNode(4,"林冲")

    val hero5 = new HeroNode(5,"关胜")

     

    root.left = hero2

    root.right = hero3

     

    hero3.left = hero5

    hero3.right = hero4

     

    val binaryTree = new BinaryTree

    binaryTree.root = root

     

    // println("前序遍历")

    // binaryTree.preOrder()

     

    // println("中序遍历")

    // binaryTree.infixOrder()

     

    // println("后序遍历")

    // binaryTree.postOrder()

     

    // val resNode = binaryTree.preOrderSearch(51)

    // if (resNode != null) {

    // printf("找到,编号=%d name=%s", resNode.no, resNode.name)

    // }else {

    // println("没有找到~")

    // }

     

    // val resNode = binaryTree.infixOrderSeacher(5)

    // if (resNode != null) {

    // printf("找到,编号=%d name=%s", resNode.no, resNode.name)

    // }else {

    // println("没有找到~")

    // }

     

    // val resNode = binaryTree.postOrderSearch(5)

    // if (resNode != null) {

    // printf("找到,编号=%d name=%s", resNode.no, resNode.name)

    // }else {

    // println("没有找到~")

    // }

     

    //测试删除节点

    binaryTree.delNode(1)

     

    println("前序遍历") // 1,2,3,4

    binaryTree.preOrder()

     

    }

    }

     

    //定义节点

    class HeroNode(hNo: Int, hName: String) {

    val no = hNo

    var name = hName

    var left: HeroNode = null

    var right: HeroNode = null

     

    //删除节点

    //删除节点规则

    //1如果删除的节点是叶子节点,则删除该节点

    //2如果删除的节点是非叶子节点,则删除该子树

     

    def delNode(no:Int): Unit = {

    //首先比较当前节点的左子节点是否为要删除的节点

    if (this.left != null && this.left.no == no) {

    this.left = null

    return

    }

    //比较当前节点的右子节点是否为要删除的节点

    if (this.right != null && this.right.no == no) {

    this.right = null

    return

    }

    //向左递归删除

    if (this.left != null) {

    this.left.delNode(no)

    }

    //向右递归删除

    if (this.right != null) {

    this.right.delNode(no)

    }

    }

     

    //后序遍历查找

    def postOrderSearch(no:Int): HeroNode = {

    //向左递归输出左子树

    var resNode:HeroNode = null

    if (this.left != null) {

    resNode = this.left.postOrderSearch(no)

    }

    if (resNode != null) {

    return resNode

    }

    if (this.right != null) {

    resNode = this.right.postOrderSearch(no)

    }

    if (resNode != null) {

    return resNode

    }

    println("ttt~~")

    if (this.no == no) {

    return this

    }

    resNode

    }

     

    //后序遍历

    def postOrder(): Unit = {

    //向左递归输出左子树

    if (this.left != null) {

    this.left.postOrder()

    }

    //向右边递归输出右子树

    if (this.right != null) {

    this.right.postOrder()

    }

    //先输出当前节点值

    printf("节点信息 no=%d name=%s ",no,name)

    }

     

    //中序遍历查找

    def infixOrderSearch(no:Int): HeroNode = {

     

     

    var resNode : HeroNode = null

    //先向左递归查找

    if (this.left != null) {

    resNode = this.left.infixOrderSearch(no)

    }

    if (resNode != null) {

    return resNode

    }

    println("yyy~~")

    if (no == this.no) {

    return this

    }

    //向右递归查找

    if (this.right != null) {

    resNode = this.right.infixOrderSearch(no)

    }

    return resNode

     

    }

     

    //中序遍历

    def infixOrder(): Unit = {

    //向左递归输出左子树

    if (this.left != null) {

    this.left.infixOrder()

    }

    //先输出当前节点值

    printf("节点信息 no=%d name=%s ",no,name)

    //向右边递归输出右子树

    if (this.right != null) {

    this.right.infixOrder()

    }

     

    }

     

    //前序查找

    def preOrderSearch(no:Int): HeroNode = {

    if (no == this.no) {

    return this

    }

    //向左递归查找

    var resNode : HeroNode = null

    if (this.left != null) {

    resNode = this.left.preOrderSearch(no)

    }

    if (resNode != null){

    return resNode

    }

    //向右边递归查找

    if (this.right != null) {

    resNode = this.right.preOrderSearch(no)

    }

     

    return resNode

    }

     

    //前序遍历

    def preOrder(): Unit = {

    //先输出当前节点值

    printf("节点信息 no=%d name=%s ",no,name)

    //向左递归输出左子树

    if (this.left != null) {

    this.left.preOrder()

    }

    //向右边递归输出右子树

    if (this.right != null) {

    this.right.preOrder()

    }

    }

    }

     

    class BinaryTree {

    var root: HeroNode = null

     

     

    def delNode(no:Int): Unit = {

    if (root != null) {

    //先处理一下root是不是要删除的

    if (root.no == no){

    root = null

    }else {

    root.delNode(no)

    }

    }

    }

     

    def postOrderSearch(no:Int): HeroNode = {

    if (root != null) {

    root.postOrderSearch(no)

    }else{

    null

    }

    }

    //后序遍历

    def postOrder(): Unit = {

    if (root != null){

    root.postOrder()

    }else {

    println("当前二叉树为空,不能遍历")

    }

    }

     

    //中序遍历查找

    def infixOrderSeacher(no:Int): HeroNode = {

    if (root != null) {

    return root.infixOrderSearch(no)

    }else {

    return null

    }

    }

     

    //中序遍历

    def infixOrder(): Unit = {

    if (root != null){

    root.infixOrder()

    }else {

    println("当前二叉树为空,不能遍历")

    }

    }

     

    //前序查找

    def preOrderSearch(no:Int): HeroNode = {

     

    if (root != null) {

    return root.preOrderSearch(no)

    }else{

    //println("当前二叉树为空,不能查找")

    return null

    }

     

    }

     

    //前序遍历

    def preOrder(): Unit = {

    if (root != null){

    root.preOrder()

    }else {

    println("当前二叉树为空,不能遍历")

    }

    }

    }

    二叉树-删除节点

    要求

    1. 如果删除的节点是叶子节点,则删除该节点
    2. 如果删除的节点是非叶子节点,则删除该子树.
    3. 测试,删除掉 5号叶子节点 3号子树.
    4. 代码,思路在代码中

    package com.atguigu.chapter18.binarytree

     

    object BinaryTreeDemo {

    def main(args: Array[String]): Unit = {

     

    //先使用比较简单方法,直接关联的方法

    val root = new HeroNode(1,"宋江")

    val hero2 = new HeroNode(2,"吴用")

    val hero3 = new HeroNode(3,"卢俊义")

    val hero4 = new HeroNode(4,"林冲")

    val hero5 = new HeroNode(5,"关胜")

     

    root.left = hero2

    root.right = hero3

     

    hero3.left = hero5

    hero3.right = hero4

     

    val binaryTree = new BinaryTree

    binaryTree.root = root

     

    // println("前序遍历")

    // binaryTree.preOrder()

     

    // println("中序遍历")

    // binaryTree.infixOrder()

     

    // println("后序遍历")

    // binaryTree.postOrder()

     

    // val resNode = binaryTree.preOrderSearch(51)

    // if (resNode != null) {

    // printf("找到,编号=%d name=%s", resNode.no, resNode.name)

    // }else {

    // println("没有找到~")

    // }

     

    // val resNode = binaryTree.infixOrderSeacher(5)

    // if (resNode != null) {

    // printf("找到,编号=%d name=%s", resNode.no, resNode.name)

    // }else {

    // println("没有找到~")

    // }

     

    // val resNode = binaryTree.postOrderSearch(5)

    // if (resNode != null) {

    // printf("找到,编号=%d name=%s", resNode.no, resNode.name)

    // }else {

    // println("没有找到~")

    // }

     

    //测试删除节点

    binaryTree.delNode(1)

     

    println("前序遍历") // 1,2,3,4

    binaryTree.preOrder()

     

    }

    }

     

    //定义节点

    class HeroNode(hNo: Int, hName: String) {

    val no = hNo

    var name = hName

    var left: HeroNode = null

    var right: HeroNode = null

     

    //删除节点

    //删除节点规则

    //1如果删除的节点是叶子节点,则删除该节点

    //2如果删除的节点是非叶子节点,则删除该子树

     

    def delNode(no:Int): Unit = {

    //首先比较当前节点的左子节点是否为要删除的节点

    if (this.left != null && this.left.no == no) {

    this.left = null

    return

    }

    //比较当前节点的右子节点是否为要删除的节点

    if (this.right != null && this.right.no == no) {

    this.right = null

    return

    }

    //向左递归删除

    if (this.left != null) {

    this.left.delNode(no)

    }

    //向右递归删除

    if (this.right != null) {

    this.right.delNode(no)

    }

    }

     

    //后序遍历查找

    def postOrderSearch(no:Int): HeroNode = {

    //向左递归输出左子树

    var resNode:HeroNode = null

    if (this.left != null) {

    resNode = this.left.postOrderSearch(no)

    }

    if (resNode != null) {

    return resNode

    }

    if (this.right != null) {

    resNode = this.right.postOrderSearch(no)

    }

    if (resNode != null) {

    return resNode

    }

    println("ttt~~")

    if (this.no == no) {

    return this

    }

    resNode

    }

     

    //后序遍历

    def postOrder(): Unit = {

    //向左递归输出左子树

    if (this.left != null) {

    this.left.postOrder()

    }

    //向右边递归输出右子树

    if (this.right != null) {

    this.right.postOrder()

    }

    //先输出当前节点值

    printf("节点信息 no=%d name=%s ",no,name)

    }

     

    //中序遍历查找

    def infixOrderSearch(no:Int): HeroNode = {

     

     

    var resNode : HeroNode = null

    //先向左递归查找

    if (this.left != null) {

    resNode = this.left.infixOrderSearch(no)

    }

    if (resNode != null) {

    return resNode

    }

    println("yyy~~")

    if (no == this.no) {

    return this

    }

    //向右递归查找

    if (this.right != null) {

    resNode = this.right.infixOrderSearch(no)

    }

    return resNode

     

    }

     

    //中序遍历

    def infixOrder(): Unit = {

    //向左递归输出左子树

    if (this.left != null) {

    this.left.infixOrder()

    }

    //先输出当前节点值

    printf("节点信息 no=%d name=%s ",no,name)

    //向右边递归输出右子树

    if (this.right != null) {

    this.right.infixOrder()

    }

     

    }

     

    //前序查找

    def preOrderSearch(no:Int): HeroNode = {

    if (no == this.no) {

    return this

    }

    //向左递归查找

    var resNode : HeroNode = null

    if (this.left != null) {

    resNode = this.left.preOrderSearch(no)

    }

    if (resNode != null){

    return resNode

    }

    //向右边递归查找

    if (this.right != null) {

    resNode = this.right.preOrderSearch(no)

    }

     

    return resNode

    }

     

    //前序遍历

    def preOrder(): Unit = {

    //先输出当前节点值

    printf("节点信息 no=%d name=%s ",no,name)

    //向左递归输出左子树

    if (this.left != null) {

    this.left.preOrder()

    }

    //向右边递归输出右子树

    if (this.right != null) {

    this.right.preOrder()

    }

    }

    }

     

    class BinaryTree {

    var root: HeroNode = null

     

     

    def delNode(no:Int): Unit = {

    if (root != null) {

    //先处理一下root是不是要删除的

    if (root.no == no){

    root = null

    }else {

    root.delNode(no)

    }

    }

    }

     

    def postOrderSearch(no:Int): HeroNode = {

    if (root != null) {

    root.postOrderSearch(no)

    }else{

    null

    }

    }

    //后序遍历

    def postOrder(): Unit = {

    if (root != null){

    root.postOrder()

    }else {

    println("当前二叉树为空,不能遍历")

    }

    }

     

    //中序遍历查找

    def infixOrderSeacher(no:Int): HeroNode = {

    if (root != null) {

    return root.infixOrderSearch(no)

    }else {

    return null

    }

    }

     

    //中序遍历

    def infixOrder(): Unit = {

    if (root != null){

    root.infixOrder()

    }else {

    println("当前二叉树为空,不能遍历")

    }

    }

     

    //前序查找

    def preOrderSearch(no:Int): HeroNode = {

     

    if (root != null) {

    return root.preOrderSearch(no)

    }else{

    //println("当前二叉树为空,不能查找")

    return null

    }

     

    }

     

    //前序遍历

    def preOrder(): Unit = {

    if (root != null){

    root.preOrder()

    }else {

    println("当前二叉树为空,不能遍历")

    }

    }

    }

     

  • 相关阅读:
    Selenium WebDriver基础操作教程
    C# 运行cmd 并 执行命令语句
    【JAVA习题二】判断101-200之间有多少个素数,并输出所有素数。
    【JAVA习题一】古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一 对兔子,假如兔子都不死,问每个月的兔子总数为多少?
    【JAVA随摘笔记一】进制转换
    【C++初学者自学笔记三】哑元函数、缺省参数、内联函数(模块二,PS:需要用到重载函数)
    【C++初学者自学笔记二】函数重载(模块一)
    【JAVA蓝桥杯】基础练习2 十六进制转十进制
    【JAVA蓝桥杯】基础练习1 十进制转十六进制
    【C++初学者自学笔记一】(把自己刚学到的东西做一下总结,如果有哪些地方不足请留言指正)
  • 原文地址:https://www.cnblogs.com/shuzhiwei/p/11209992.html
Copyright © 2011-2022 走看看