- 将数列 {1, 3, 6, 8, 10, 14 } 构建成一颗二叉树

| 当我们对上面的二叉树进行中序遍历时,数列为 {8, 3, 10, 1, 6, 14 } |
| 但是 6, 8, 10, 14 这几个节点的左右指针,并没有完全的利用上. |
| 如果我们希望充分的利用各个节点的左右指针,让各个节点可以指向自己的前后节点 |
| 解决方案:线索二叉树 |
| n个结点的二叉链表中含有n+1 【公式 2n-(n-1)=n+1】 个空指针域。利用二叉链表中的空指针域,存放指向该结点在某种遍历次序下的前驱和后继结点的指针(这种附加的指针称为"线索") |
| |
| 这种加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树(Threaded BinaryTree)。根据线索性质的不同,线索二叉树可分为前序线索二叉树、中序线索二叉树和后序线索二叉树三种 |
| |
| 一个结点的前一个结点,称为前驱结点,例如在数列{8, 3, 10, 1, 6, 14 }中3的前驱结点是8 |
| 一个结点的后一个结点,称为后继结点 |
- 如下二叉树中序遍历后的数组为{8, 3, 10, 1, 14, 6}

| 根据中序遍历的顺序 |
| 先看节点8,后继节点指向3,再看3,3的左右指针不为空,再看10,10的左右指针为空,那么10的前驱节点指向3,10的后继节点就指向1,依次类推 |
| |
| 当线索化二叉树后,Node节点的 属性 left 和 right ,有如下情况: |
| left 指向的是左子树,也可能是指向的前驱节点. 比如 ① 节点 left 指向的左子树, 而 ⑩ 节点的 left 指向的就是前驱节点. |
| right指向的是右子树,也可能是指向后继节点,比如 ① 节点right 指向的是右子树,而⑩ 节点的right 指向的是后继节点 |
| 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.threadedNodes(); |
| |
| |
| HeroNode leftNode = node5.getLeft(); |
| HeroNode rightNode = node5.getRight(); |
| System.out.println("10号结点的前驱结点是 =" + leftNode); |
| System.out.println("10号结点的后继结点是=" + rightNode); |
| } |
| |
| } |
| |
| |
| class ThreadedBinaryTree { |
| |
| |
| |
| private HeroNode pre = null; |
| |
| |
| public void threadedNodes() { |
| this.threadedNodes(root); |
| } |
| |
| |
| |
| |
| |
| public void threadedNodes(HeroNode node) { |
| |
| if(node == null) { |
| return; |
| } |
| |
| threadedNodes(node.getLeft()); |
| |
| |
| |
| |
| if(node.getLeft() == null) { |
| |
| node.setLeft(pre); |
| |
| node.setLeftType(1); |
| } |
| |
| if (pre != null && pre.getRight() == null) { |
| |
| pre.setRight(node); |
| |
| pre.setRightType(1); |
| } |
| |
| pre = node; |
| |
| threadedNodes(node.getRight()); |
| } |
| |
| } |
| |
| |
| class HeroNode { |
| |
| |
| |
| private int leftType; |
| private int rightType; |
| } |
| 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.threadedNodes(); |
| |
| |
| HeroNode leftNode = node5.getLeft(); |
| HeroNode rightNode = node5.getRight(); |
| System.out.println("10号结点的前驱结点是 =" + leftNode); |
| System.out.println("10号结点的后继结点是=" + rightNode); |
| |
| |
| |
| |
| System.out.println("使用线索化的方式遍历 线索化二叉树"); |
| threadedBinaryTree.threadedList(); |
| } |
| |
| } |
| |
| |
| class ThreadedBinaryTree { |
| |
| |
| public void threadedList() { |
| |
| HeroNode node = root; |
| while(node != null) { |
| |
| |
| |
| 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(); |
| } |
| } |
| |
| } |
点击查看详情
| package com.atguigu.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.threadedNodes(); |
| |
| |
| HeroNode leftNode = node5.getLeft(); |
| HeroNode rightNode = node5.getRight(); |
| System.out.println("10号结点的前驱结点是 =" + leftNode); |
| System.out.println("10号结点的后继结点是=" + rightNode); |
| |
| |
| |
| |
| System.out.println("使用线索化的方式遍历 线索化二叉树"); |
| threadedBinaryTree.threadedList(); |
| |
| } |
| |
| } |
| |
| |
| class ThreadedBinaryTree { |
| private HeroNode root; |
| |
| |
| |
| private HeroNode pre = null; |
| |
| public void setRoot(HeroNode root) { |
| this.root = root; |
| } |
| |
| |
| public void threadedNodes() { |
| this.threadedNodes(root); |
| } |
| |
| |
| public void threadedList() { |
| |
| HeroNode node = root; |
| while(node != null) { |
| |
| |
| |
| 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(); |
| } |
| } |
| |
| |
| |
| |
| |
| public void threadedNodes(HeroNode node) { |
| |
| if(node == null) { |
| return; |
| } |
| |
| threadedNodes(node.getLeft()); |
| |
| |
| |
| |
| if(node.getLeft() == null) { |
| |
| node.setLeft(pre); |
| |
| node.setLeftType(1); |
| } |
| |
| if (pre != null && pre.getRight() == null) { |
| |
| pre.setRight(node); |
| |
| pre.setRightType(1); |
| } |
| |
| pre = node; |
| |
| threadedNodes(node.getRight()); |
| } |
| |
| |
| public void delNode(int no) { |
| if(root != null) { |
| |
| if(root.getNo() == no) { |
| root = null; |
| } else { |
| |
| root.delNode(no); |
| } |
| }else{ |
| System.out.println("空树,不能删除~"); |
| } |
| } |
| |
| |
| 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 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 this.root.postOrderSearch(no); |
| }else { |
| return null; |
| } |
| } |
| |
| } |
| |
| |
| class HeroNode { |
| private int no; |
| private String name; |
| private HeroNode left; |
| private HeroNode right; |
| |
| |
| |
| private int leftType; |
| private int rightType; |
| |
| public int getLeftType() { |
| return leftType; |
| } |
| public void setLeftType(int leftType) { |
| this.leftType = leftType; |
| } |
| public int getRightType() { |
| return rightType; |
| } |
| public void setRightType(int rightType) { |
| this.rightType = rightType; |
| } |
| public HeroNode(int no, String name) { |
| this.no = no; |
| this.name = name; |
| } |
| public int getNo() { |
| return no; |
| } |
| public void setNo(int no) { |
| this.no = no; |
| } |
| public String getName() { |
| return name; |
| } |
| public void setName(String name) { |
| this.name = name; |
| } |
| public HeroNode getLeft() { |
| return left; |
| } |
| public void setLeft(HeroNode left) { |
| this.left = left; |
| } |
| public HeroNode getRight() { |
| return right; |
| } |
| public void setRight(HeroNode right) { |
| this.right = right; |
| } |
| @Override |
| public String toString() { |
| return "HeroNode [no=" + no + ", name=" + name + "]"; |
| } |
| |
| |
| |
| |
| 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); |
| } |
| } |
| |
| |
| public void preOrder() { |
| System.out.println(this); |
| |
| 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); |
| |
| 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); |
| } |
| |
| |
| |
| |
| |
| |
| public HeroNode preOrderSearch(int no) { |
| System.out.println("进入前序遍历"); |
| |
| if(this.no == no) { |
| return this; |
| } |
| |
| |
| HeroNode resNode = 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; |
| } |
| |
| |
| public HeroNode infixOrderSearch(int no) { |
| |
| HeroNode resNode = null; |
| if(this.left != null) { |
| resNode = this.left.infixOrderSearch(no); |
| } |
| if(resNode != null) { |
| return resNode; |
| } |
| System.out.println("进入中序查找"); |
| |
| if(this.no == no) { |
| return this; |
| } |
| |
| if(this.right != null) { |
| resNode = this.right.infixOrderSearch(no); |
| } |
| return resNode; |
| } |
| |
| |
| public HeroNode postOrderSearch(int no) { |
| |
| HeroNode resNode = 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; |
| } |
| System.out.println("进入后序查找"); |
| |
| if(this.no == no) { |
| return this; |
| } |
| return resNode; |
| } |
| |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术