树结构基础部分

二叉树

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

  1. 数组存储方式的分析
    ① 优点:通过下标方式访问元素,速度快。对于有序数组,还可使用二分查找提高检索速度。
    ② 缺点:如果要检索具体某个值,或者插入值(按一定顺序)会整体移动,效率较低。

  2. 链式存储方式的分析
    ① 优点:在一定程度上对数组存储方式有优化(比如:插入一个数值节点,只需要将插入节点,链接到链表中即可, 删除效率也很好)。
    ② 缺点:在进行检索时,效率仍然较低,比如(检索某个值,需要从头节点开始遍历) 。

  3. 树存储方式的分析
    ① 能提高数据存储,读取的效率, 比如利用 二叉排序树(Binary Sort Tree),既可以保证数据的检索速度,同时也可以保证数据的插入,删除,修改的速度。
    案例:[7,3,10,1,5,9,12]

树的示意图

二叉树的概念

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

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

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

  1. 应用实例的思路和说明

代码

package tree;public class BinaryTreeDemo {public static void main(String[] args) {// 现需要创建一棵二叉树BinaryTree binaryTree = new BinaryTree();// 创建需要的结点HeroNode root = new HeroNode(1,"宋江");HeroNode node2 = new HeroNode(2,"吴用");HeroNode node3 = new HeroNode(3,"卢俊义");HeroNode node4 = new HeroNode(4,"林冲");HeroNode node5 = new HeroNode(5,"关胜");// 说明:先手动创建该二叉树,后面以递归方式创建二叉树root.setLeft(node2);root.setRight(node3);node3.setRight(node4);binaryTree.setRoot(root);// 测试System.out.println("前序遍历测试"); // 1,2,3,4binaryTree.preOrder();System.out.println("中序遍历测试"); // 2,1,3,4binaryTree.infixOrder();System.out.println("后序遍历测试"); // 2,4,3,1binaryTree.postOrder();// 3号添加左节点node3.setLeft(node5);System.out.println("前序遍历测试"); // 1,2,3,5,4binaryTree.preOrder();System.out.println("中序遍历测试"); // 2,1,5,3,4binaryTree.infixOrder();System.out.println("后序遍历测试"); // 2,5,4,3,1binaryTree.postOrder();}
}// 定义一个BinaryTree 二叉树
class BinaryTree{private HeroNode root;public void setRoot(HeroNode root) {this.root = root;}// 前序遍历public void preOrder(){if(this.root != null){this.root.preOrder();}else{System.out.println("二叉树为空,无法遍历!");}}// 中序遍历public void infixOrder(){if(this.root != null){this.root.infixOrder();}else{System.out.println("二叉树为空,无法遍历!");}}public void postOrder(){if(this.root != null){this.root.postOrder();}else{System.out.println("二叉树为空,无法遍历!");}}
}// 先创建HeroNode 结点
class HeroNode {private int no;private String name;private HeroNode left;  // 默认nullprivate HeroNode right;  // 默认nullpublic HeroNode(int no, String name) {super();this.no = no;this.name = name;}public int getNo() {return no;}public String getName() {return name;}public HeroNode getLeft() {return left;}public HeroNode getRight() {return right;}public void setNo(int no) {this.no = no;}public void setName(String name) {this.name = name;}public void setLeft(HeroNode left) {this.left = left;}public void setRight(HeroNode right) {this.right = right;}@Overridepublic String toString() {return "HeroNode{" +"no=" + no +", name='" + name + '\'' +'}';}// 编写前序遍历方法public void preOrder() {System.out.println(this.toString());    // 先输出父节点// 递归向左子树前序遍历if (this.left != null) {this.left.preOrder();}// 递归向右子树前序遍历if (this.right != null) {this.right.preOrder();}}// 编写中序遍历方法public void infixOrder() {// 递归向左子树中序遍历if (this.left != null) {this.left.infixOrder();}// 输出父节点System.out.println(this.toString());// 递归向右子树中序遍历if (this.right != null) {this.right.infixOrder();}}// 编写后序遍历方法public void postOrder() {// 递归向左子树中序遍历if (this.left != null) {this.left.postOrder();}// 递归向右子树中序遍历if (this.right != null) {this.right.postOrder();}// 输出父节点System.out.println(this.toString());}
}

二叉树-查找指定节点

要求

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

代码

package tree;public class BinaryTreeDemo {public static void main(String[] args) {// 现需要创建一棵二叉树BinaryTree binaryTree = new BinaryTree();// 创建需要的结点HeroNode root = new HeroNode(1,"宋江");HeroNode node2 = new HeroNode(2,"吴用");HeroNode node3 = new HeroNode(3,"卢俊义");HeroNode node4 = new HeroNode(4,"林冲");HeroNode node5 = new HeroNode(5,"关胜");// 说明:先手动创建该二叉树,后面以递归方式创建二叉树root.setLeft(node2);root.setRight(node3);node3.setRight(node4);binaryTree.setRoot(root);// 查询测试node3.setLeft(node5);// 前序遍历查询:// 遍历次数:4System.out.println("前序遍历查询");HeroNode preResultNode = binaryTree.preOrderSearch(5);if(preResultNode != null){System.out.printf("找到了,信息为 : no = %d name = %s\n",preResultNode.getNo(),preResultNode.getName());}else{System.out.printf("没有找到编号为 %d 的英雄",5);}// 中序遍历查询:// 遍历次数:3System.out.println("中序遍历查询");HeroNode infixResultNode = binaryTree.infixOrderSearch(5);if(preResultNode != null){System.out.printf("找到了,信息为 : no = %d name = %s\n",preResultNode.getNo(),preResultNode.getName());}else{System.out.printf("没有找到编号为 %d 的英雄",5);}// 后序遍历查询:// 遍历次数:2System.out.println("后序遍历查询");HeroNode postResultNode = binaryTree.postOrderSearch(5);if(preResultNode != null){System.out.printf("找到了,信息为 : no = %d name = %s\n",preResultNode.getNo(),preResultNode.getName());}else{System.out.printf("没有找到编号为 %d 的英雄",5);}}
}// 定义一个BinaryTree 二叉树
class BinaryTree{private HeroNode root;public void setRoot(HeroNode root) {this.root = root;}// 前序遍历查询public HeroNode preOrderSearch(int no){if(root != null){return root.preOrderSearch(no);}else{return null;}}// 中序遍历查询public HeroNode infixOrderSearch(int no){if(root != null){return root.infixOrderSearch(no);}else{return null;}}// 后续遍历查询public HeroNode postOrderSearch(int no){if(root != null){return root.postOrderSearch(no);}else{return null;}}
}// 先创建HeroNode 结点
class HeroNode {private int no;private String name;private HeroNode left;  // 默认nullprivate HeroNode right;  // 默认nullpublic HeroNode(int no, String name) {super();this.no = no;this.name = name;}public int getNo() {return no;}public String getName() {return name;}public HeroNode getLeft() {return left;}public HeroNode getRight() {return right;}public void setNo(int no) {this.no = no;}public void setName(String name) {this.name = name;}public void setLeft(HeroNode left) {this.left = left;}public void setRight(HeroNode right) {this.right = right;}@Overridepublic String toString() {return "HeroNode{" +"no=" + no +", name='" + name + '\'' +'}';}// 前序遍历查找public HeroNode preOrderSearch(int no){// 比较当前节点是不是if(this.no == no){return this;}// 1. 判断当前结点左子节点是否为空,如果不为空,递归前序查找// 2. 如果左递归前序查找,找到结点,则返回HeroNode resultNode = null;if(this.left != null){resultNode = this.left.preOrderSearch(no);}if(resultNode != null){// 说明在左子树找到结果return resultNode;}// 3. 否则继续判断,咋判断当前结点的右子节点是否为空,如果不空,继续向右递归前序查找if(this.right != null){resultNode = this.right.preOrderSearch(no);}return resultNode;}// 中序遍历查找public HeroNode infixOrderSearch(int no){HeroNode resultNode = null;if(this.left != null){resultNode = this.left.infixOrderSearch(no);}if(resultNode != null){return resultNode;}if(this.no == no){return this;}if(this.right != null){resultNode = this.right.infixOrderSearch(no);}return resultNode;}// 后序遍历查找public HeroNode postOrderSearch(int no){HeroNode resultNode = null;if(this.left != null){resultNode = this.left.postOrderSearch(no);}if(resultNode != null){return resultNode;}if(this.right != null){resultNode = this.right.postOrderSearch(no);}if(resultNode != null){return resultNode;}if(this.no == no){resultNode = this;}return resultNode;}
}

二叉树-删除节点

要求

  1. 如果删除的节点是叶子节点,则删除该节点
  2. 如果删除的节点是非叶子节点,则删除该子树.
  3. 测试,删除掉 5号叶子节点 和 3号子树.
  4. 思路分析图解

代码

package tree;public class BinaryTreeDemo {public static void main(String[] args) {// 现需要创建一棵二叉树BinaryTree binaryTree = new BinaryTree();// 创建需要的结点HeroNode root = new HeroNode(1, "宋江");HeroNode node2 = new HeroNode(2, "吴用");HeroNode node3 = new HeroNode(3, "卢俊义");HeroNode node4 = new HeroNode(4, "林冲");HeroNode node5 = new HeroNode(5, "关胜");// 说明:先手动创建该二叉树,后面以递归方式创建二叉树root.setLeft(node2);root.setRight(node3);node3.setRight(node4);binaryTree.setRoot(root);/*// 遍历测试System.out.println("前序遍历测试"); // 1,2,3,4binaryTree.preOrder();System.out.println("中序遍历测试"); // 2,1,3,4binaryTree.infixOrder();System.out.println("后序遍历测试"); // 2,4,3,1binaryTree.postOrder();// 3号添加左节点node3.setLeft(node5);System.out.println("前序遍历测试"); // 1,2,3,5,4binaryTree.preOrder();System.out.println("中序遍历测试"); // 2,1,5,3,4binaryTree.infixOrder();System.out.println("后序遍历测试"); // 2,5,4,3,1binaryTree.postOrder();*//*// 查询测试node3.setLeft(node5);// 前序遍历查询:// 遍历次数:4System.out.println("前序遍历查询");HeroNode preResultNode = binaryTree.preOrderSearch(5);if (preResultNode != null) {System.out.printf("找到了,信息为 : no = %d name = %s\n", preResultNode.getNo(), preResultNode.getName());} else {System.out.printf("没有找到编号为 %d 的英雄", 5);}// 中序遍历查询:// 遍历次数:3System.out.println("中序遍历查询");HeroNode infixResultNode = binaryTree.infixOrderSearch(5);if (preResultNode != null) {System.out.printf("找到了,信息为 : no = %d name = %s\n", preResultNode.getNo(), preResultNode.getName());} else {System.out.printf("没有找到编号为 %d 的英雄", 5);}// 后序遍历查询:// 遍历次数:2System.out.println("后序遍历查询");HeroNode postResultNode = binaryTree.postOrderSearch(5);if (preResultNode != null) {System.out.printf("找到了,信息为 : no = %d name = %s\n", preResultNode.getNo(), preResultNode.getName());} else {System.out.printf("没有找到编号为 %d 的英雄", 5);}*/// 删除测试node3.setLeft(node5);System.out.println("删除前,前序遍历");binaryTree.preOrder();  // 1,2,3,5,4// binaryTree.delNode(5);binaryTree.delNode(3);System.out.println("删除后,前序遍历");binaryTree.preOrder();  // 1,2,3,4}
}// 定义一个BinaryTree 二叉树
class BinaryTree {private HeroNode root;public void setRoot(HeroNode root) {this.root = root;}// 删除节点public void delNode(int no) {if (root != null) {// 如果只有一个root,这里立即判断root是否是需要删除的节点if (root.getNo() == no) {root = null;} else {// 递归删除root.delNode(no);}} else {System.out.println("空树,无法删除");}}
}// 先创建HeroNode 结点
class HeroNode {private int no;private String name;private HeroNode left;  // 默认nullprivate HeroNode right;  // 默认nullpublic HeroNode(int no, String name) {super();this.no = no;this.name = name;}public int getNo() {return no;}public String getName() {return name;}public HeroNode getLeft() {return left;}public HeroNode getRight() {return right;}public void setNo(int no) {this.no = no;}public void setName(String name) {this.name = name;}public void setLeft(HeroNode left) {this.left = left;}public void setRight(HeroNode right) {this.right = right;}@Overridepublic String toString() {return "HeroNode{" +"no=" + no +", name='" + name + '\'' +'}';}// 递归删除节点// 暂时规定:// 1. 如果删除的节点是叶子节点,则删除该节点// 2. 如果删除的节点是非叶子节点,则删除该子树public void delNode(int no) {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);}}
}

顺序存储二叉树

顺序存储二叉树的概念

  • 基本说明
    从数据存储来看,数组存储方式和树的存储方式可以相互转换,即数组可以转换成树,树也可以转换成数组,可看示意图。

    要求:
    图中的二叉树的结点,要求以数组的方式来存放 arr : [1, 2, 3, 4, 5, 6, 7]
    要求在遍历数组 arr时,仍然可以以前序遍历,中序遍历和后序遍历的方式完成结点的遍历
  • 顺序存储二叉树的特点:
  1. 顺序二叉树通常只考虑完全二叉树
  2. 第n个元素的左子节点为 2 * n + 1
  3. 第n个元素的右子节点为 2 * n + 2
  4. 第n个元素的父节点为 (n-1) / 2
  5. n : 表示二叉树中的第几个元素(按0开始编号如图所示)

顺序存储二叉树遍历

需求: 给你一个数组 {1,2,3,4,5,6,7},要求以二叉树前序遍历的方式进行遍历。 前序遍历的结果应当为 1,2,4,5,3,6,7
课后练习:完成对数组以二叉树中序,后序遍历方式的代码.

代码

package tree;import java.util.ArrayList;public class ArrBinaryTreeDemo {public static void main(String[] args) {int[] arr = {1, 2, 3, 4, 5, 6, 7};// 创建一个ArrayBinaryTreeArrayBinaryTree arrayBinaryTree = new ArrayBinaryTree(arr);arrayBinaryTree.preOrder();    // 1,2,4,5,3,6,7}
}// 编写一个ArrayBinaryTree类
class ArrayBinaryTree {private int[] arr;  // 存储数据节点的数组public ArrayBinaryTree(int[] arr) {this.arr = arr;}// 重载preOrderpublic void preOrder(){this.preOrder(0);}public void infixOrder(){this.infixOrder(0);}public void postOrder(){this.postOrder(0);}// 编写一个方法,完成顺序存储二叉树的前序遍历/*** @param index 数组下标*/public void preOrder(int index) {// 如果数组为空,或者arr.length() = 0if (arr == null || arr.length == 0) {System.out.println("数组为空,不能按照二叉树的前序遍历");}// 输出当前元素System.out.println(arr[index]);// 向左递归遍历if ((index) * 2 + 1 < arr.length) {preOrder(2 * index + 1);}if ((index) * 2 + 2 < arr.length) {preOrder(2 * index + 2);}}/*** @param index 数组下标*/public void infixOrder(int index) {// 如果数组为空,或者arr.length() = 0if (arr == null || arr.length == 0) {System.out.println("数组为空,不能按照二叉树的中序遍历");}// 向左递归遍历if ((index) * 2 + 1 < arr.length) {infixOrder(2 * index + 1);}// 输出当前元素System.out.println(arr[index]);if ((index) * 2 + 2 < arr.length) {infixOrder(2 * index + 2);}}/*** @param index 数组下标*/public void postOrder(int index) {// 如果数组为空,或者arr.length() = 0if (arr == null || arr.length == 0) {System.out.println("数组为空,不能按照二叉树的后序遍历");}// 向左递归遍历if ((index) * 2 + 1 < arr.length) {postOrder(2 * index + 1);}// 输出当前元素System.out.println(arr[index]);if ((index) * 2 + 2 < arr.length) {postOrder(2 * index + 2);}}
}

顺序存储二叉树应用实例

八大排序算法中的堆排序,就会使用到顺序存储二叉树。

线索化二叉树

一个问题

将数列 {1, 3, 6, 8, 10, 14 } 构建成一颗二叉树. n+1=7

问题分析:

  1. 当我们对上面的二叉树进行中序遍历时,数列为 {8, 3, 10, 1, 6, 14 }
  2. 但是 6, 8, 10, 14 这几个节点的 左右指针,并没有完全的利用上.
  3. 如果我们希望充分的利用 各个节点的左右指针, 让各个节点可以指向自己的前后节点,怎么办?
  4. 解决方案-线索二叉树

线索二叉树基本介绍

  1. n个结点的二叉链表中含有n+1 【公式 2n-(n-1)=n+1】 个空指针域。利用二叉链表中的空指针域,存放指向该结点在某种遍历次序下的前驱和后继结点的指针(这种附加的指针称为"线索")
  2. 这种加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树(Threaded BinaryTree)。根据线索性质的不同,线索二叉树可分为前序线索二叉树、中序线索二叉树和后序线索二叉树三种
  3. 一个结点的前一个结点,称为前驱结点
  4. 一个结点的后一个结点,称为后继结点

应用案例说明:将下面的二叉树,进行中序线索二叉树。中序遍历的数列为 {8, 3, 10, 1, 14, 6}


思路分析:

遍历线索化二叉树

  1. 说明:对前面的中序线索化的二叉树, 进行遍历
  2. 分析:因为线索化后,各个结点指向有变化,因此原来的遍历方式不能使用,这时需要使用新的方式遍历线索化二叉树,各个节点可以通过线型方式遍历,因此无需使用递归方式,这样也提高了遍历的效率。 遍历的次序应当和中序遍历保持一致。

代码

package tree.threadedbinarytree;public class ThreadedBinaryTreeDemo {public static void main(String[] args) {// 测试中序线索二叉树HeroNode root = new HeroNode(1, "tom");HeroNode node2 = new HeroNode(3, "jack");HeroNode node3 = new HeroNode(6, "smith");HeroNode node4 = new HeroNode(8, "mary");HeroNode node5 = new HeroNode(10, "king");HeroNode node6 = new HeroNode(14, "dim");// 二叉树创建root.setLeft(node2);root.setRight(node3);node2.setLeft(node4);node2.setRight(node5);node3.setLeft(node6);ThreadedBinaryTree threadedBinaryTree = new ThreadedBinaryTree();threadedBinaryTree.setRoot(root);threadedBinaryTree.infixThreadedNodes();// 测试:以node5为测试
//        System.out.println(node4.getLeft());
//        System.out.println(node5.getRight());System.out.println("使用线索化的方式遍历线索化二叉树");threadedBinaryTree.threadedList();}
}// 定义一个ThreadedBinaryTree 二叉树
class ThreadedBinaryTree {private tree.threadedbinarytree.HeroNode root;// 为了实现线索化,需要创建给要给指向当前结点的前驱节点的指针// 在递归线索化的过程中,pre总是指向前一个节点private HeroNode pre = null;public void setRoot(tree.threadedbinarytree.HeroNode root) {this.root = root;}// 遍历线索化二叉树方法public void threadedList() {// 定义一个变量,存储当前遍历的结点,从root开始HeroNode node = root;while (node != null) {// 循环找到leftType = 1的结点,第一个找到8的结点// 后面随着遍历leftType变化,因为当leftType=1的时候,说明该节点是按照线索化处理后的有效节点while (node.getLeftType() == 0) {node = node.getLeft();}// 打印当前结点System.out.println(node);// 如果当前结点右指针指向后继结点,就一直输出while (node.getRightType() == 1) {// 获取到当前结点的后继节点node = node.getRight();System.out.println(node);}// 替换遍历的结点node = node.getRight();}}// 重载infixThreadedNodespublic void infixThreadedNodes() {this.infixThreadedNodes(root);}/*** 编写对二叉树进行中序线索化的方法** @param node 就是当前需要线索化的结点*/public void infixThreadedNodes(HeroNode node) {// 如果当前结点为空,不需要线索化if (node == null) {return;}// 1)先线索化左子树infixThreadedNodes(node.getLeft());// 2)线索化当前结点// ① 先处理当前结点前驱节点if (node.getLeft() == null) {// 让当前结点的左指针指向前驱节点node.setLeft(pre);// 修改当前结点的左指针的类型,指向前驱节点node.setLeftType(1);}// ② 处理后继节点if (pre != null && pre.getRight() == null) {// 让前驱结点的右指针指向当前结点pre.setRight(node);// 修改前驱节点的右指针类型pre.setRightType(1);}// ★★★★★★★★五角星每处理一个节点后,让当前结点称为下一个节点的前驱节点pre = node;// 3)再线索化右子树infixThreadedNodes(node.getRight());}// 前序遍历public void preOrder() {if (this.root != null) {this.root.preOrder();} else {System.out.println("二叉树为空,无法遍历!");}}// 中序遍历public void infixOrder() {if (this.root != null) {this.root.infixOrder();} else {System.out.println("二叉树为空,无法遍历!");}}// 后序遍历public void postOrder() {if (this.root != null) {this.root.postOrder();} else {System.out.println("二叉树为空,无法遍历!");}}// 前序遍历查询public tree.threadedbinarytree.HeroNode preOrderSearch(int no) {if (root != null) {return root.preOrderSearch(no);} else {return null;}}// 中序遍历查询public tree.threadedbinarytree.HeroNode infixOrderSearch(int no) {if (root != null) {return root.infixOrderSearch(no);} else {return null;}}// 后续遍历查询public tree.threadedbinarytree.HeroNode postOrderSearch(int no) {if (root != null) {return root.postOrderSearch(no);} else {return null;}}// 删除节点public void delNode(int no) {if (root != null) {// 如果只有一个root,这里立即判断root是否是需要删除的节点if (root.getNo() == no) {root = null;} else {// 递归删除root.delNode(no);}} else {System.out.println("空树,无法删除");}}
}class HeroNode {private int no;private String name;private tree.threadedbinarytree.HeroNode left;  // 默认nullprivate tree.threadedbinarytree.HeroNode right;  // 默认null// 定义属性区分// 说明:// 1. 如果leftType == 0 表示指向的是左子树 如果是1表示指向前驱节点// 2. 如果rightType == 0 表示指向的是右子树 如果是1表示指向后继节点private int leftType;private int rightType;public void setLeftType(int leftType) {this.leftType = leftType;}public void setRightType(int rightType) {this.rightType = rightType;}public int getLeftType() {return leftType;}public int getRightType() {return rightType;}public HeroNode(int no, String name) {super();this.no = no;this.name = name;}public int getNo() {return no;}public String getName() {return name;}public tree.threadedbinarytree.HeroNode getLeft() {return left;}public tree.threadedbinarytree.HeroNode getRight() {return right;}public void setNo(int no) {this.no = no;}public void setName(String name) {this.name = name;}public void setLeft(tree.threadedbinarytree.HeroNode left) {this.left = left;}public void setRight(tree.threadedbinarytree.HeroNode right) {this.right = right;}@Overridepublic String toString() {return "HeroNode{" +"no=" + no +", name='" + name + '\'' +'}';}// 编写前序遍历方法public void preOrder() {System.out.println(this.toString());    // 先输出父节点// 递归向左子树前序遍历if (this.left != null) {this.left.preOrder();}// 递归向右子树前序遍历if (this.right != null) {this.right.preOrder();}}// 编写中序遍历方法public void infixOrder() {// 递归向左子树中序遍历if (this.left != null) {this.left.infixOrder();}// 输出父节点System.out.println(this.toString());// 递归向右子树中序遍历if (this.right != null) {this.right.infixOrder();}}// 编写后序遍历方法public void postOrder() {// 递归向左子树中序遍历if (this.left != null) {this.left.postOrder();}// 递归向右子树中序遍历if (this.right != null) {this.right.postOrder();}// 输出父节点System.out.println(this.toString());}// 前序遍历查找public tree.threadedbinarytree.HeroNode preOrderSearch(int no) {// 比较当前节点是不是if (this.no == no) {return this;}// 1. 判断当前结点左子节点是否为空,如果不为空,递归前序查找// 2. 如果左递归前序查找,找到结点,则返回tree.threadedbinarytree.HeroNode resultNode = null;if (this.left != null) {resultNode = this.left.preOrderSearch(no);}if (resultNode != null) {// 说明在左子树找到结果return resultNode;}// 3. 否则继续判断,咋判断当前结点的右子节点是否为空,如果不空,继续向右递归前序查找if (this.right != null) {resultNode = this.right.preOrderSearch(no);}return resultNode;}// 中序遍历查找public tree.threadedbinarytree.HeroNode infixOrderSearch(int no) {tree.threadedbinarytree.HeroNode resultNode = null;if (this.left != null) {resultNode = this.left.infixOrderSearch(no);}if (resultNode != null) {return resultNode;}if (this.no == no) {return this;}if (this.right != null) {resultNode = this.right.infixOrderSearch(no);}return resultNode;}// 后序遍历查找public tree.threadedbinarytree.HeroNode postOrderSearch(int no) {tree.threadedbinarytree.HeroNode resultNode = null;if (this.left != null) {resultNode = this.left.postOrderSearch(no);}if (resultNode != null) {return resultNode;}if (this.right != null) {resultNode = this.right.postOrderSearch(no);}if (resultNode != null) {return resultNode;}if (this.no == no) {resultNode = this;}return resultNode;}// 递归删除节点// 暂时规定:// 1. 如果删除的节点是叶子节点,则删除该节点// 2. 如果删除的节点是非叶子节点,则删除该子树public void delNode(int no) {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);}}
}

Java编程:树(基础部分)相关推荐

  1. JAVA编程入门基础

    JAVA编程入门 程序=算法+数据结构 用户使用编程语言实现问题域到解域的映射,细节描述算法 1.汇编语言-贴近于硬件设备 2.高级语言-C#.Java-贴近于自然语言-需要编译过程将高级语言所编写的 ...

  2. 穿越障碍物JAVA编程_JAVA 基础编程练习题1 【程序 1 不死神兔】

    1 [程序 1 不死神兔] 题目:古典问题:有一对兔子,从出生后第 3 个月起每个月都生一对兔子,小兔子长到第三个月后每个月 又生一对兔子,假如兔子都不死,问每个月的兔子对数为多少? 程序分析: 兔子 ...

  3. java 以一个最高有效位为1的二进制数字开始_第02章 Java编程基础

    ·本章学习目标 熟悉Java编程的基础知识 掌握Java语言的基本数据类型.操作符.表达式 掌握Java程序的流程控制语句 熟悉并学会初步使用Java编程环境 ·本章学习内容 数据类型 常量.变量与表 ...

  4. java nextline_Java编程语言基础的9根支柱

    Java编程的基础概念包括:数据类型,分支与循环等. 1.HelloWorld 先从最简单的Java程序开始: public class HelloWorld{ public static void ...

  5. 从事java编程技能要求_5道Java视频课程,提高您的编程技能

    从事java编程技能要求 作为Web开发人员,跟上技术知识可能会很棘手. 新技术似乎每天都在弹出,而基本技术也看到了重复迭代的浪潮,增加了新的功能. Java开发人员应该做什么? 这是在线教育平台发挥 ...

  6. java编程自学教程笔记,大量教程

    武汉Java编程入门怎么学?让大家的Java编程入门.一.Java编程零基础可以学,但自学的确阻力有些大.作为一门技术语言,它所蕴含的智慧不是靠一些基础知识,而更多 接下来就要学习的是Java的面向对 ...

  7. java怎么提升编程能力_怎样提升java编程能力

    1 怎样提升java编程能力 在互联网迅猛发展的时代,而我们如果对互联网一无所知,那就相当于文盲.所以很多人都想去了解它,去学习他.而作为互联网的产物--java,是一门非常不错的技术,学精通之后,你 ...

  8. Java编程兵书,在实战中体会编程的快乐,初学和自学者的福音

    前言 Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 面向对象程序设计语言和 Java 平台的总称.由 James Gosling和同事们共同研发,并在 ...

  9. java编程自学教程(超详细版)

    一:学习路线(流程) 1阶段Java核心基础 2阶段数据库核心技术 3阶段JavaWeb核心技术 4阶段企业必备技术 5阶段Java大厂提升技术 6阶段大型项目与解决方案 7阶段大厂必备面试 二:学习 ...

  10. 怎么学习Java编程,Java初学者指南

    怎么学习Java编程,Java初学者指南.Java基于C和C++.第一个Java编译器是由Sun Microsystems开发的,是使用C++中的一些库用C编写的.Java文件使用编译器转换为位代码格 ...

最新文章

  1. dedecms首页去掉index.html怎么设置
  2. Linux文件实时同步--inotify + rsync + pyinotify
  3. 熟悉的亲切-老外婆教做的豌豆蔬菜汤
  4. 终于编译好了qt的oracle驱动QOCI,连接成功!!!
  5. 在iOS中求数组元素中最大数与最小数
  6. 节前福利 | 三位大佬带你从客户成功、销售、市场端打造 To B 运作体系 !
  7. Boost:bind绑定一元地址的测试程序
  8. MSSQLSERVER服务不能启动
  9. php动态+trait,详解PHP神奇又有用的Trait
  10. P4123-[CQOI2016]不同的最小割【网络流,分治】
  11. 网站实现点击 “加入收藏 ”功能 - 代码篇
  12. Martin Odersky Scala编程公开课 第二周作业
  13. AI产品经理需要了解的数据知识:余弦相似度
  14. 【ML】理解偏差和方差,过拟合和欠拟合
  15. ZOJ 3686 A Simple Tree Problem
  16. bzoj3223Tyvj 1729 文艺平衡树 splay
  17. hack tool Mirkov4
  18. 阿里云ace考试有什么用?想要通过需要掌握哪些方面知识?
  19. ReactNative动画之Animated初识篇
  20. 论文笔记《Modeling Task Relationships in Multi-task Learning with Multi-gate Mixture-of-Experts》

热门文章

  1. 18.TCP/IP 详解卷1 --- TCP 连接的建立与终止
  2. 24.事务控制和锁定语句
  3. java lang ClassNotFoundException org apache jsp index jsp解决
  4. Linux大棚命令记录
  5. setTimeout 带参数调用问题
  6. [what is machine learning?]
  7. CentOS 上MySQL报错Can't connect to local Mysql server through socket '/tmp/mysql.scok' (111)
  8. MineCraft note
  9. 利用第三方库XML解析 (TBXML)转化成模型数据
  10. marquee标签制作轮播图