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

    树通常结合了另外两种数据结构的优点:一种是有序数组,另一种是链表。在树中查找数据项的速度和在有序数组中查找一样快,并且插入数据项和删除数据项的速度也和链表一样。

    1、二叉搜索树:一个节点的左子节点的关键字值小于这个节点,右子节点的关键字值大于或等于这个父节点。

    // to run this program: C>java TreeApp
    import java.io.*;
    import java.util.*;          
    class TreeNode
    {
       public int data;               
       public TreeNode leftChild;       
       public TreeNode rightChild;
       public TreeNode parent;  
     
       public TreeNode(int data,TreeNode leftChild
                       ,TreeNode rightChild,TreeNode parent)
       {
          this.data = data;
          this.leftChild = leftChild;
          this.rightChild = rightChild;
          this.parent = parent;
       }    
    
       public int getData()     
       {
          return this.data;
       }
    } 
    
    class BinarySearchTree
    {
       private TreeNode root;       
    
       public BinarySearchTree()               
       {  root = null;  }   
    
       public TreeNode getRoot()
       {  return this.root;  }
    
    //判断二叉查找树是否为空;
      public boolean isEmpty()
      {
         if(root==null)
            return true;
         else
            return false;
      }       
    
       //在二叉查找树中查询给定关键字
       public TreeNode find(int key) 
       {                           
          TreeNode currentNode = root;         
          while(currentNode!=null && currentNode.data!=key)
          {
             if(key < currentNode.data)
                currentNode = currentNode.leftChild;
              else 
                currentNode = currentNode.rightChild;
          } 
          return currentNode;            
       } 
      
       //查找二叉查找树中的最小关键字节点
       public TreeNode minNode(TreeNode node)
       {
           if(node ==null)
              return null;
           TreeNode currentNode = node;
           while(currentNode.leftChild!=null)
              currentNode = currentNode.leftChild;
           return currentNode;
       }
    
       //查找二叉查找树中的最大关键字节点
       public TreeNode maxNode(TreeNode node)
       {
          if(node ==null)
             return null;
          TreeNode currentNode = node;
          while(currentNode.rightChild!=null)
             currentNode = currentNode.rightChild;
          return currentNode;
       }
     
       //前序遍历
       public void preOrder(TreeNode node)
       {
          if(node != null)
          {
             System.out.print(node.data + " ");
             preOrder(node.leftChild);
             preOrder(node.rightChild);
          }
       }
    
       //中序遍历
       public  void inOrder(TreeNode node)
       {
          if(node != null)
          {
             inOrder(node.leftChild);
             System.out.print(node.data + " ");
             inOrder(node.rightChild);
          }
       }
    
       //中序遍历,每个节点显示前驱和后继节点
       public  void testNode(TreeNode node)
       {
          if(node != null)
          {
             testNode(node.leftChild);
             TreeNode node1 = getPrecessor(node);
             TreeNode node2 = getSuccessor(node);
             System.out.print("本节点:"+node.getData());
             if(node1 != null)
                System.out.print("    前驱节点:"+node1.getData());
             else
                System.out.print("    没有前驱节点");
             if(node2 != null)
                System.out.print("    后继节点:"+node2.getData());
             else
                System.out.print("    没有后继节点");
            System.out.println("");
            testNode(node.rightChild);
          }
       }
    
       //后序遍历
       public  void postOrder(TreeNode node)
       {
          if(node != null)
          {
             postOrder(node.leftChild);
             postOrder(node.rightChild);
             System.out.print(node.data + " ");
          }
       }
    
       //插入节点
       public void insert(int key)
       {
          TreeNode newNode = new TreeNode(key,null,null,null); 
          if(root == null)
          {
             root = newNode;
             return;
          }           
          TreeNode currentNode = root;
          TreeNode parentNode = null;
          while(currentNode != null)
          {
             parentNode = currentNode;
             if(key < currentNode.data)
                currentNode = currentNode.leftChild;
             else if(key > currentNode.data)
                currentNode = currentNode.rightChild;
             else
             //树中已存在匹配给定关键字的节点,则什么都不做直接返回
                return;
          }
        //parentNode就是最后一个非空的节点
          if(key < parentNode.data)
          {
             parentNode.leftChild = newNode;
             newNode.parent = parentNode;
          }
          else
          {
             parentNode.rightChild = newNode;
             newNode.parent = parentNode;
          }
       }   
    
       //删除节点
       public boolean delete(TreeNode node)
       {          
          TreeNode currentNode = node;
          if(currentNode == null)
             return false;
       
    //key节点没有孩子 if(currentNode.leftChild == null && currentNode.rightChild == null) { //key节点是根节点 if(currentNode == root) { root = null; return true; } //key节点是其父节点的左孩子 TreeNode parentNode = currentNode.parent; if(currentNode ==parentNode.leftChild) parentNode.leftChild = null; //key节点是其父节点的右孩子 else parentNode.rightChild = null; return true; } //key节点只有左孩子 if(currentNode.leftChild != null && currentNode.rightChild == null) { //key节点是根节点 if(currentNode == root) { root = currentNode.leftChild; root.parent=null; return true; } //key节点是其父节点的左孩子 TreeNode parentNode = currentNode.parent; if(currentNode == parentNode.leftChild) { parentNode.leftChild = currentNode.leftChild; currentNode.leftChild.parent = parentNode; } //key节点是其父节点的右孩子 else { parentNode.rightChild = currentNode.leftChild; currentNode.leftChild.parent = parentNode; } return true; } //key节点只有右孩子 if(currentNode.leftChild == null && currentNode.rightChild != null) { //key节点是根节点 if(currentNode == root) { root = currentNode.rightChild; root.parent = null; return true; } //key节点是其父节点的左孩子 TreeNode parentNode = currentNode.parent; if(currentNode == currentNode.parent.leftChild) { parentNode.leftChild = currentNode.rightChild; currentNode.rightChild.parent = parentNode; } //key节点是其父节点的右孩子 else { parentNode.rightChild = currentNode.rightChild; currentNode.rightChild.parent = parentNode; } return true; } //key节点左右孩子都有 if(currentNode.leftChild != null && currentNode.rightChild != null) { TreeNode successorNode = getSuccessor(currentNode); delete(successorNode); currentNode.data = successorNode.data; } return true; } //查找给定节点在中序遍历下的后继节点 private TreeNode getSuccessor(TreeNode node) { //子树为空 if(node == null) return null; //若该节点的右子树不为空,则其后继节点就是右子树中的最小关键字节点 if(node.rightChild!=null) return minNode(node.rightChild); //若该节点右子树为空,则向上一直找它的祖先,直到一个祖先是另一个祖先的左孩子 TreeNode parentNode = node.parent; while(parentNode!=null && node==parentNode.rightChild) { node = parentNode; parentNode = parentNode.parent; } return parentNode; } //查找给定节点在中序遍历下的前驱节点 public TreeNode getPrecessor(TreeNode node) { //子树为空 if(node == null) return null; //若该节点的左子树不为空,则其后继节点就是右子树中的最大关键字节点 if(node.leftChild!=null) return maxNode(node.leftChild); //若该节点左子树为空,则向上一直找它的祖先,直到一个祖先是另一个祖先的右孩子 TreeNode parentNode = node.parent; while(parentNode!=null && node == parentNode.leftChild) { node = parentNode; parentNode = parentNode.parent; } return parentNode; } } class BinarySearchTreeApp { public static void main(String[] args) throws IOException { BinarySearchTree bst = new BinarySearchTree(); System.out.print("二叉查找树是否为空?"); if(bst.isEmpty()==true) System.out.println("是"); else System.out.println("否"); int[] keys = new int[] { 15, 6, 18, 3, 7, 13, 20, 2, 9, 4 }; // int[] keys = new int[] { }; for(int key : keys) bst.insert(key); System.out.print("二叉查找树是否为空?"); if(bst.isEmpty()==true) System.out.println("是"); else System.out.println("否"); System.out.print("根节点关键字: " ); if(bst.getRoot()!=null) System.out.println(bst.getRoot().getData());
    System.out.print(
    "最小关键字: "); if(bst.getRoot()!=null) System.out.println( bst.minNode(bst.getRoot()).getData()); System.out.print("最大关键字: "); if(bst.getRoot()!=null) System.out.println( + bst.maxNode(bst.getRoot()).getData()); System.out.print("前序遍历: " ); bst.preOrder(bst.getRoot()); System.out.println(""); System.out.print("中序遍历: " ); bst.inOrder(bst.getRoot()); System.out.println(""); System.out.print("后序遍历: " ); bst.postOrder(bst.getRoot()); System.out.println(""); bst.testNode(bst.getRoot()); //删除13这个节点 TreeNode node = bst.find(13); bst.delete(node); node = null; System.out.println(""); System.out.print("中序遍历: " ); bst.inOrder(bst.getRoot()); System.out.println(""
    ); bst.testNode(bst.getRoot()); }
    }
    二叉查找树是否为空?是
    二叉查找树是否为空?否
    根节点关键字: 15
    最小关键字: 2
    最大关键字: 20
    前序遍历: 15 6 3 2 4 7 13 9 18 20 
    中序遍历: 2 3 4 6 7 9 13 15 18 20 
    后序遍历: 2 4 3 9 13 7 6 20 18 15 
    本节点:2    没有前驱节点    后继节点:3
    本节点:3    前驱节点:2    后继节点:4
    本节点:4    前驱节点:3    后继节点:6
    本节点:6    前驱节点:4    后继节点:7
    本节点:7    前驱节点:6    后继节点:9
    本节点:9    前驱节点:7    后继节点:13
    本节点:13    前驱节点:9    后继节点:15
    本节点:15    前驱节点:13    后继节点:18
    本节点:18    前驱节点:15    后继节点:20
    本节点:20    前驱节点:18    没有后继节点
    
    中序遍历: 2 3 4 6 7 9 15 18 20 
    本节点:2    没有前驱节点    后继节点:3
    本节点:3    前驱节点:2    后继节点:4
    本节点:4    前驱节点:3    后继节点:6
    本节点:6    前驱节点:4    后继节点:7
    本节点:7    前驱节点:6    后继节点:9
    本节点:9    前驱节点:7    后继节点:15
    本节点:15    前驱节点:9    后继节点:18
    本节点:18    前驱节点:15    后继节点:20
    本节点:20    前驱节点:18    没有后继节点
  • 相关阅读:
    Laravel schema构建器列类型
    wkhtmltopdf docker + java(环境搭建及一些坑)
    dockerfile,仓库,私有仓库流程(转载)
    wkhtmltopdf参数详解及精讲使用方法(转载)
    传统前端项目中进行模块化编程并引入使用vue、elementui 前端
    vue3 + vuex4 实践 前端
    elementplus 原生开发 日期国际化语言 前端
    Vite2.0打包elementplus UI报错 前端
    vue3 Vetur报错:has no default export 组件没导出 前端
    windows版的HbuilderX连接iPad真机测试(uniapp)
  • 原文地址:https://www.cnblogs.com/xxlong/p/4995973.html
Copyright © 2011-2022 走看看