Java编程内功-数据结构与算法「树」

开发 后端 算法
本片继续给大家介绍关于Java编程数据结构与算法的相关内容,今天主要介绍树这种结构。

[[388287]]

 为什么需要树这种结构

1.数组存储方式分析:

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

2.链式存储方式分析:

  • 优点:在一定程度上对数组存储方式优化(比如:插入一个数值节点,只需要将插入节点,链接到链表中即可,删除效率很高)。
  • 缺点:在进行检索时,效率仍然很低,需要从头结点开始遍历。

3.树存储方式分析:能提高数据存储,读取的效率,比如利用二叉排序树(Binary sort tree),即可以保证数据的检索速度,同时也可以保证数据的插入、删除、修改的速度。假设一组[7,3,10,1,5,9,12]以树的方式存储,分析如下图:


二叉树的前序遍历、中序遍历、后序遍历

  • 前序遍历:输出父节点、输出左边节点、输出右边节点;
  • 中序遍历:输出左边节点、输出父节点、输出右边节点;
  • 后序遍历:输出左边节点、输出右边节点、输出父节点;

需求案例

完成一个如下二叉树节点存储、前序遍历搜索、中序遍历搜索、后序遍历搜索和删除节点功能。

对于删除节点要求如下:

  1. 如果删除的节点是叶子节点,则删除该节点。
  2. 如果删除的节点是非叶子节点,则删除该树。
  3. 测试,删除5号叶子节点和3号子树。

代码案例

  1. package com.xie.tree; 
  2.  
  3. public class BinaryTreeDemo { 
  4.  
  5.     public static void main(String[] args) { 
  6.         BinaryTree binaryTree = new BinaryTree(); 
  7.  
  8.         HeroNode root = new HeroNode(1, "宋江"); 
  9.         HeroNode node2 = new HeroNode(2, "吴用"); 
  10.         HeroNode node3 = new HeroNode(3, "卢俊义"); 
  11.         HeroNode node4 = new HeroNode(4, "林冲"); 
  12.         HeroNode node5 = new HeroNode(5, "关胜"); 
  13.  
  14.         //先手动创建该二叉树,后面用递归方式 
  15.         root.setLeft(node2); 
  16.         root.setRight(node3); 
  17.         node3.setRight(node4); 
  18.         node3.setLeft(node5); 
  19.  
  20.         binaryTree.setRoot(root); 
  21.  
  22.         //前序遍历 
  23.         System.out.println("前序遍历"); 
  24.         binaryTree.preOrder(); 
  25.  
  26.         //中序遍历 
  27.         System.out.println("中序遍历"); 
  28.         binaryTree.infixOrder(); 
  29.  
  30.         //后续遍历 
  31.         System.out.println("后续遍历"); 
  32.         binaryTree.postOrder(); 
  33.  
  34.         //前序遍历查找 
  35.         System.out.println("前序遍历查找~~"); 
  36.         HeroNode resultNode = binaryTree.preOrderSearch(5); 
  37.         if (resultNode != null) { 
  38.             System.out.printf("找到了,信息为no=%d,name=%s\n", resultNode.getNo(), resultNode.getName()); 
  39.             System.out.println("遍历次数:" + HeroNode.preCount); 
  40.         } else { 
  41.             System.out.println("没有找到"); 
  42.         } 
  43.  
  44.         //中序遍历查找 
  45.         System.out.println("中序遍历查找~~"); 
  46.         HeroNode resultNode1 = binaryTree.infixOrderSearch(5); 
  47.         if (resultNode1 != null) { 
  48.             System.out.printf("找到了,信息为no=%d,name=%s\n", resultNode1.getNo(), resultNode1.getName()); 
  49.             System.out.println("遍历次数:" + HeroNode.infoxCount); 
  50.         } else { 
  51.             System.out.println("没有找到"); 
  52.         } 
  53.  
  54.         //后序遍历查找 
  55.         System.out.println("后序遍历查找~~"); 
  56.         HeroNode resultNode2 = binaryTree.postOrderSearch(5); 
  57.         if (resultNode2 != null) { 
  58.             System.out.printf("找到了,信息为no=%d,name=%s\n", resultNode2.getNo(), resultNode2.getName()); 
  59.             System.out.println("遍历次数:" + HeroNode.postCount); 
  60.         } else { 
  61.             System.out.println("没有找到"); 
  62.         } 
  63.  
  64.         System.out.println("删除3号节点"); 
  65.         binaryTree.delNo(3); 
  66.         System.out.println("删除后的节点"); 
  67.         binaryTree.preOrder(); 
  68.         /** 
  69.          * 前序遍历 
  70.          * HeroNode{no=1, name=宋江} 
  71.          * HeroNode{no=2, name=吴用} 
  72.          * HeroNode{no=3, name=卢俊义} 
  73.          * HeroNode{no=5, name=关胜} 
  74.          * HeroNode{no=4, name=林冲} 
  75.          * 中序遍历 
  76.          * HeroNode{no=2, name=吴用} 
  77.          * HeroNode{no=1, name=宋江} 
  78.          * HeroNode{no=5, name=关胜} 
  79.          * HeroNode{no=3, name=卢俊义} 
  80.          * HeroNode{no=4, name=林冲} 
  81.          * 后续遍历 
  82.          * HeroNode{no=2, name=吴用} 
  83.          * HeroNode{no=5, name=关胜} 
  84.          * HeroNode{no=4, name=林冲} 
  85.          * HeroNode{no=3, name=卢俊义} 
  86.          * HeroNode{no=1, name=宋江} 
  87.          * 前序遍历查找~~ 
  88.          * 找到了,信息为no=5,name=关胜 
  89.          * 遍历次数:4 
  90.          * 中序遍历查找~~ 
  91.          * 找到了,信息为no=5,name=关胜 
  92.          * 遍历次数:3 
  93.          * 后序遍历查找~~ 
  94.          * 找到了,信息为no=5,name=关胜 
  95.          * 遍历次数:2 
  96.          * 删除3号节点 
  97.          * 删除后的节点 
  98.          * HeroNode{no=1, name=宋江} 
  99.          * HeroNode{no=2, name=吴用} 
  100.          */ 
  101.     } 
  102.  
  103. class BinaryTree { 
  104.     private HeroNode root; 
  105.  
  106.     public void setRoot(HeroNode root) { 
  107.         this.root = root; 
  108.     } 
  109.  
  110.     //前序遍历 
  111.     public void preOrder() { 
  112.         if (this.root != null) { 
  113.             this.root.preOrder(); 
  114.         } 
  115.     } 
  116.  
  117.     //中序遍历 
  118.     public void infixOrder() { 
  119.         if (this.root != null) { 
  120.             this.root.infixOrder(); 
  121.         } 
  122.     } 
  123.  
  124.     //删除节点 
  125.     public void delNo(int no) { 
  126.         if (this.root != null) { 
  127.             if (this.root.getNo() == no) { 
  128.                 this.root = null
  129.             } else { 
  130.                 this.root.delNo(no); 
  131.             } 
  132.         } 
  133.         return
  134.     } 
  135.  
  136.     //后序遍历 
  137.     public void postOrder() { 
  138.         if (this.root != null) { 
  139.             this.root.postOrder(); 
  140.         } 
  141.     } 
  142.  
  143.     //前序遍历查找 
  144.     public HeroNode preOrderSearch(int no) { 
  145.         if (root != null) { 
  146.             return root.preOrderSearch(no); 
  147.         } else { 
  148.             return null
  149.         } 
  150.     } 
  151.  
  152.     //中序遍历查找 
  153.     public HeroNode infixOrderSearch(int no) { 
  154.         if (root != null) { 
  155.             return root.infixOrderSearch(no); 
  156.         } else { 
  157.             return null
  158.         } 
  159.     } 
  160.  
  161.     //后序遍历查找 
  162.     public HeroNode postOrderSearch(int no) { 
  163.         if (root != null) { 
  164.             return root.postOrderSearch(no); 
  165.         } else { 
  166.             return null
  167.         } 
  168.     } 
  169.  
  170. class HeroNode { 
  171.     static int preCount = 0; 
  172.     static int infoxCount = 0; 
  173.     static int postCount = 0; 
  174.  
  175.     private int no
  176.     private String name
  177.     private HeroNode left
  178.     private HeroNode right
  179.  
  180.     public HeroNode(int no, String name) { 
  181.         this.no = no
  182.         this.name = name
  183.     } 
  184.  
  185.     public int getNo() { 
  186.         return no
  187.     } 
  188.  
  189.     public void setNo(int no) { 
  190.         this.no = no
  191.     } 
  192.  
  193.     public String getName() { 
  194.         return name
  195.     } 
  196.  
  197.     public void setName(String name) { 
  198.         this.name = name
  199.     } 
  200.  
  201.     public HeroNode getLeft() { 
  202.         return left
  203.     } 
  204.  
  205.     public void setLeft(HeroNode left) { 
  206.         this.left = left
  207.     } 
  208.  
  209.     public HeroNode getRight() { 
  210.         return right
  211.     } 
  212.  
  213.     public void setRight(HeroNode right) { 
  214.         this.right = right
  215.     } 
  216.  
  217.     @Override 
  218.     public String toString() { 
  219.         return "HeroNode{" + 
  220.                 "no=" + no + 
  221.                 ", name=" + name + 
  222.                 '}'
  223.     } 
  224.  
  225.     //前序遍历 
  226.     public void preOrder() { 
  227.         System.out.println(this); 
  228.         //递归向左子树前序遍历 
  229.         if (this.left != null) { 
  230.             this.left.preOrder(); 
  231.         } 
  232.  
  233.         //递归向右子树前序遍历 
  234.         if (this.right != null) { 
  235.             this.right.preOrder(); 
  236.         } 
  237.     } 
  238.  
  239.     //中序遍历 
  240.     public void infixOrder() { 
  241.         //递归向左子树中序遍历 
  242.         if (this.left != null) { 
  243.             this.left.infixOrder(); 
  244.         } 
  245.         System.out.println(this); 
  246.         //递归向右子树中序遍历 
  247.         if (this.right != null) { 
  248.             this.right.infixOrder(); 
  249.         } 
  250.     } 
  251.  
  252.     //后序遍历 
  253.     public void postOrder() { 
  254.         //递归向左子树后序遍历 
  255.         if (this.left != null) { 
  256.             this.left.postOrder(); 
  257.         } 
  258.         //递归向右子树后序遍历 
  259.         if (this.right != null) { 
  260.             this.right.postOrder(); 
  261.         } 
  262.         System.out.println(this); 
  263.     } 
  264.  
  265.     //递归删除节点 
  266.     //1.如果删除的节点是叶子节点,则删除该节点。 
  267.     //2.如果删除的节点是非叶子节点,则删除该树。 
  268.     public void delNo(int no) { 
  269.         /** 
  270.          * 1.因为我们的二叉树是单向的,所以我们是判断当前节点的子节点是否是需要删除的节点,而不能去判断当前节点是否是需要删除的节点。 
  271.          * 2.如果当前节点的左子节点不为空,并且左子节点就是需要删除的节点,就将this.left = null;并且返回(结束递归)。 
  272.          * 3.如果当前节点的右子节点不为空,并且右子节点就是需要删除的节点,将将this.right = null;并且返回(结束递归)。 
  273.          * 4.如果第2步和第3步没有删除节点,那么就要向左子树进行递归删除。 
  274.          * 5.如果第4步也没有删除节点,则应当向右子树进行递归删除。 
  275.          */ 
  276.         if (this.left != null && this.left.no == no) { 
  277.             this.left = null
  278.             return
  279.         } 
  280.  
  281.         if (this.right != null && this.right.no == no) { 
  282.             this.right = null
  283.             return
  284.         } 
  285.  
  286.         if (this.left != null) { 
  287.             this.left.delNo(no); 
  288.         } 
  289.  
  290.         if (this.right != null) { 
  291.             this.right.delNo(no); 
  292.         } 
  293.  
  294.     } 
  295.  
  296.     //前序遍历查找 
  297.     public HeroNode preOrderSearch(int no) { 
  298.  
  299.         HeroNode res = null
  300.  
  301.         preCount++;//这里必须放在this.no == no 判断之前,才进行实际的比较 
  302.         //若果找到,就返回 
  303.         if (this.no == no) { 
  304.             return this; 
  305.         } 
  306.         //没有找到,向左子树递归进行前序查找 
  307.         if (this.left != null) { 
  308.             res = this.left.preOrderSearch(no); 
  309.         } 
  310.         //如果res != null 就直接返回 
  311.         if (res != null) { 
  312.             return res; 
  313.         } 
  314.         //如果左子树没有找打,向右子树进行前序查找 
  315.         if (this.right != null) { 
  316.             res = this.right.preOrderSearch(no); 
  317.         } 
  318.         //如果找到就返回 
  319.         if (res != null) { 
  320.             return res; 
  321.         } 
  322.         return res; 
  323.     } 
  324.  
  325.     //中序遍历查找 
  326.     public HeroNode infixOrderSearch(int no) { 
  327.  
  328.         HeroNode res = null
  329.         if (this.left != null) { 
  330.             res = this.left.infixOrderSearch(no); 
  331.         } 
  332.         if (res != null) { 
  333.             return res; 
  334.         } 
  335.         infoxCount++;//这里必须放在this.no == no 判断之前,才进行实际的比较 
  336.         if (this.no == no) { 
  337.             return this; 
  338.         } 
  339.         if (this.right != null) { 
  340.             res = this.right.infixOrderSearch(no); 
  341.         } 
  342.         if (res != null) { 
  343.             return res; 
  344.         } 
  345.         return res; 
  346.     } 
  347.  
  348.     //后序遍历查找 
  349.     public HeroNode postOrderSearch(int no) { 
  350.  
  351.         HeroNode res = null
  352.         if (this.left != null) { 
  353.             res = this.left.postOrderSearch(no); 
  354.         } 
  355.         if (res != null) { 
  356.             return res; 
  357.         } 
  358.  
  359.         if (this.right != null) { 
  360.             res = this.right.postOrderSearch(no); 
  361.         } 
  362.         if (res != null) { 
  363.             return res; 
  364.         } 
  365.         postCount++;//这里必须放在this.no == no 判断之前,才进行实际的比较 
  366.         if (this.no == no) { 
  367.             return this; 
  368.         } 
  369.         return res; 
  370.     } 

 【编辑推荐】

 

责任编辑:姜华 来源: 今日头条
相关推荐

2021-04-07 09:26:37

Java数据结构算法

2021-03-24 10:41:04

Java数据结构算法

2021-05-12 09:07:09

Java数据结构算法

2021-03-09 06:30:32

JAVA数据结构算法

2021-04-13 09:37:41

Java数据结构算法

2021-03-12 09:13:47

Java数据结构算法

2021-03-26 08:40:28

Java数据结构算法

2021-03-23 08:33:22

Java数据结构算法

2021-03-10 08:42:19

Java数据结构算法

2021-03-08 06:28:57

JAVA数据结构与算法稀疏数组

2021-03-17 09:27:36

Java数据结构算法

2021-04-01 10:34:18

Java编程数据结构算法

2021-03-19 10:25:12

Java数据结构算法

2021-03-29 10:13:47

Java编程数据结构算法

2021-04-15 09:36:44

Java数据结构算法

2021-04-22 10:07:45

Java数据结构算法

2021-03-14 08:27:40

Java数据结构算法

2021-04-16 09:40:52

Java数据结构算法

2021-03-22 09:00:22

Java数据结构算法

2021-05-13 07:34:56

Java数据结构算法
点赞
收藏

51CTO技术栈公众号