java实现二叉查找树

  1. /**  
  2.  * @author zyj8170  2011-2-13  
  3.  *   
  4.  * 此程序实现一个二叉查找树的功能,可以进行动态插入、删除关键字;  
  5.  * 查询给定关键字、最小关键字、最大关键字;转换为有序列表(用于排序)  
  6.  *   
  7.  *   
  8.  */  
  9.   
  10. import java.util.ArrayList;  
  11. import java.util.List;  
  12.   
  13. public class BinarySearchTree {  
  14.   
  15.     // 树的根结点  
  16.     private TreeNode root = null;  
  17.   
  18.     // 遍历结点列表  
  19.     private List<TreeNode> nodelist = new ArrayList<TreeNode>();  
  20.   
  21.     private class TreeNode {  
  22.   
  23.         private int key;  
  24.         private TreeNode leftChild;  
  25.         private TreeNode rightChild;  
  26.         private TreeNode parent;  
  27.   
  28.         public TreeNode(int key, TreeNode leftChild, TreeNode rightChild,  
  29.                 TreeNode parent) {  
  30.             this.key = key;  
  31.             this.leftChild = leftChild;  
  32.             this.rightChild = rightChild;  
  33.             this.parent = parent;  
  34.         }  
  35.   
  36.         public int getKey() {  
  37.             return key;  
  38.         }  
  39.   
  40.         public String toString() {  
  41.             String leftkey = (leftChild == null ? "" : String  
  42.                     .valueOf(leftChild.key));  
  43.             String rightkey = (rightChild == null ? "" : String  
  44.                     .valueOf(rightChild.key));  
  45.             return "(" + leftkey + " , " + key + " , " + rightkey + ")";  
  46.         }  
  47.   
  48.     }  
  49.   
  50.     /** 
  51.      * isEmpty: 判断二叉查找树是否为空;若为空,返回 true ,否则返回 false . 
  52.      *  
  53.      */  
  54.     public boolean isEmpty() {  
  55.         if (root == null) {  
  56.             return true;  
  57.         } else {  
  58.             return false;  
  59.         }  
  60.     }  
  61.   
  62.     /** 
  63.      * TreeEmpty: 对于某些二叉查找树操作(比如删除关键字)来说,若树为空,则抛出异常。 
  64.      */  
  65.     public void TreeEmpty() throws Exception {  
  66.         if (isEmpty()) {  
  67.             throw new Exception("树为空!");  
  68.         }  
  69.     }  
  70.   
  71.     /** 
  72.      * search: 在二叉查找树中查询给定关键字 
  73.      *  
  74.      * @param key 
  75.      *            给定关键字 
  76.      * @return 匹配给定关键字的树结点 
  77.      */  
  78.     public TreeNode search(int key) {  
  79.         TreeNode pNode = root;  
  80.         while (pNode != null && pNode.key != key) {  
  81.             if (key < pNode.key) {  
  82.                 pNode = pNode.leftChild;  
  83.             } else {  
  84.                 pNode = pNode.rightChild;  
  85.             }  
  86.         }  
  87.         return pNode;  
  88.     }  
  89.   
  90.     /** 
  91.      * minElemNode: 获取二叉查找树中的最小关键字结点 
  92.      *  
  93.      * @return 二叉查找树的最小关键字结点 
  94.      * @throws Exception 
  95.      *             若树为空,则抛出异常 
  96.      */  
  97.     public TreeNode minElemNode(TreeNode node) throws Exception {  
  98.         if (node == null) {  
  99.             throw new Exception("树为空!");  
  100.         }  
  101.         TreeNode pNode = node;  
  102.         while (pNode.leftChild != null) {  
  103.             pNode = pNode.leftChild;  
  104.         }  
  105.         return pNode;  
  106.     }  
  107.   
  108.     /** 
  109.      * maxElemNode: 获取二叉查找树中的最大关键字结点 
  110.      *  
  111.      * @return 二叉查找树的最大关键字结点 
  112.      * @throws Exception 
  113.      *             若树为空,则抛出异常 
  114.      */  
  115.     public TreeNode maxElemNode(TreeNode node) throws Exception {  
  116.         if (node == null) {  
  117.             throw new Exception("树为空!");  
  118.         }  
  119.         TreeNode pNode = node;  
  120.         while (pNode.rightChild != null) {  
  121.             pNode = pNode.rightChild;  
  122.         }  
  123.         return pNode;  
  124.     }  
  125.   
  126.     /** 
  127.      * successor: 获取给定结点在中序遍历顺序下的后继结点 
  128.      *  
  129.      * @param node 
  130.      *            给定树中的结点 
  131.      * @return 若该结点存在中序遍历顺序下的后继结点,则返回其后继结点;否则返回 null 
  132.      * @throws Exception 
  133.      */  
  134.     public TreeNode successor(TreeNode node) throws Exception {  
  135.         if (node == null) {  
  136.             return null;  
  137.         }  
  138.   
  139.         // 若该结点的右子树不为空,则其后继结点就是右子树中的最小关键字结点  
  140.         if (node.rightChild != null) {  
  141.             return minElemNode(node.rightChild);  
  142.         }  
  143.         // 若该结点右子树为空  
  144.         TreeNode parentNode = node.parent;  
  145.         while (parentNode != null && node == parentNode.rightChild) {  
  146.             node = parentNode;  
  147.             parentNode = parentNode.parent;  
  148.         }  
  149.         return parentNode;  
  150.     }  
  151.   
  152.     /** 
  153.      * precessor: 获取给定结点在中序遍历顺序下的前趋结点 
  154.      *  
  155.      * @param node 
  156.      *            给定树中的结点 
  157.      * @return 若该结点存在中序遍历顺序下的前趋结点,则返回其前趋结点;否则返回 null 
  158.      * @throws Exception 
  159.      */  
  160.     public TreeNode precessor(TreeNode node) throws Exception {  
  161.         if (node == null) {  
  162.             return null;  
  163.         }  
  164.   
  165.         // 若该结点的左子树不为空,则其前趋结点就是左子树中的最大关键字结点  
  166.         if (node.leftChild != null) {  
  167.             return maxElemNode(node.leftChild);  
  168.         }  
  169.         // 若该结点左子树为空  
  170.         TreeNode parentNode = node.parent;  
  171.         while (parentNode != null && node == parentNode.leftChild) {  
  172.             node = parentNode;  
  173.             parentNode = parentNode.parent;  
  174.         }  
  175.         return parentNode;  
  176.     }  
  177.   
  178.     /** 
  179.      * insert: 将给定关键字插入到二叉查找树中 
  180.      *  
  181.      * @param key 
  182.      *            给定关键字 
  183.      */  
  184.     public void insert(int key) {  
  185.         TreeNode parentNode = null;  
  186.         TreeNode newNode = new TreeNode(key, null, null, null);  
  187.         TreeNode pNode = root;  
  188.         if (root == null) {  
  189.             root = newNode;  
  190.             return;  
  191.         }  
  192.         while (pNode != null) {  
  193.             parentNode = pNode;  
  194.             if (key < pNode.key) {  
  195.                 pNode = pNode.leftChild;  
  196.             } else if (key > pNode.key) {  
  197.                 pNode = pNode.rightChild;  
  198.             } else {  
  199.                 // 树中已存在匹配给定关键字的结点,则什么都不做直接返回  
  200.                 return;  
  201.             }  
  202.         }  
  203.         if (key < parentNode.key) {  
  204.             parentNode.leftChild = newNode;  
  205.             newNode.parent = parentNode;  
  206.         } else {  
  207.             parentNode.rightChild = newNode;  
  208.             newNode.parent = parentNode;  
  209.         }  
  210.   
  211.     }  
  212.   
  213.     /** 
  214.      * insert: 从二叉查找树中删除匹配给定关键字相应的树结点 
  215.      *  
  216.      * @param key 
  217.      *            给定关键字 
  218.      */  
  219.     public void delete(int key) throws Exception {  
  220.         TreeNode pNode = search(key);  
  221.         if (pNode == null) {  
  222.             throw new Exception("树中不存在要删除的关键字!");  
  223.         }  
  224.         delete(pNode);  
  225.     }  
  226.   
  227.     /** 
  228.      * delete: 从二叉查找树中删除给定的结点. 
  229.      *  
  230.      * @param pNode 
  231.      *            要删除的结点 
  232.      *  
  233.      *            前置条件: 给定结点在二叉查找树中已经存在 
  234.      * @throws Exception 
  235.      */  
  236.     private void delete(TreeNode pNode) throws Exception {  
  237.         if (pNode == null) {  
  238.             return;  
  239.         }  
  240.         if (pNode.leftChild == null && pNode.rightChild == null) { // 该结点既无左孩子结点,也无右孩子结点  
  241.             TreeNode parentNode = pNode.parent;  
  242.             if (pNode == parentNode.leftChild) {  
  243.                 parentNode.leftChild = null;  
  244.             } else {  
  245.                 parentNode.rightChild = null;  
  246.             }  
  247.             return;  
  248.         }  
  249.         if (pNode.leftChild == null && pNode.rightChild != null) { // 该结点左孩子结点为空,右孩子结点非空  
  250.             TreeNode parentNode = pNode.parent;  
  251.             if (pNode == parentNode.leftChild) {  
  252.                 parentNode.leftChild = pNode.rightChild;  
  253.                 pNode.rightChild.parent = parentNode;  
  254.             } else {  
  255.                 parentNode.rightChild = pNode.rightChild;  
  256.                 pNode.rightChild.parent = parentNode;  
  257.             }  
  258.             return;  
  259.         }  
  260.         if (pNode.leftChild != null && pNode.rightChild == null) { // 该结点左孩子结点非空,右孩子结点为空  
  261.             TreeNode parentNode = pNode.parent;  
  262.             if (pNode == parentNode.leftChild) {  
  263.                 parentNode.leftChild = pNode.leftChild;  
  264.                 pNode.rightChild.parent = parentNode;  
  265.             } else {  
  266.                 parentNode.rightChild = pNode.leftChild;  
  267.                 pNode.rightChild.parent = parentNode;  
  268.             }  
  269.             return;  
  270.         }  
  271.         // 该结点左右孩子结点均非空,则删除该结点的后继结点,并用该后继结点取代该结点  
  272.         TreeNode successorNode = successor(pNode);  
  273.         delete(successorNode);  
  274.         pNode.key = successorNode.key;  
  275.     }  
  276.   
  277.     /** 
  278.      * inOrderTraverseList: 获得二叉查找树的中序遍历结点列表 
  279.      *  
  280.      * @return 二叉查找树的中序遍历结点列表 
  281.      */  
  282.     public List<TreeNode> inOrderTraverseList() {  
  283.         if (nodelist != null) {  
  284.             nodelist.clear();  
  285.         }  
  286.         inOrderTraverse(root);  
  287.         return nodelist;  
  288.     }  
  289.   
  290.     /** 
  291.      * inOrderTraverse: 对给定二叉查找树进行中序遍历 
  292.      *  
  293.      * @param root 
  294.      *            给定二叉查找树的根结点 
  295.      */  
  296.     private void inOrderTraverse(TreeNode root) {  
  297.         if (root != null) {  
  298.             inOrderTraverse(root.leftChild);  
  299.             nodelist.add(root);  
  300.             inOrderTraverse(root.rightChild);  
  301.         }  
  302.     }  
  303.   
  304.     /** 
  305.      * toStringOfOrderList: 获取二叉查找树中关键字的有序列表 
  306.      *  
  307.      * @return 二叉查找树中关键字的有序列表 
  308.      */  
  309.     public String toStringOfOrderList() {  
  310.         StringBuilder sbBuilder = new StringBuilder(" [ ");  
  311.         for (TreeNode p : inOrderTraverseList()) {  
  312.             sbBuilder.append(p.key);  
  313.             sbBuilder.append(" ");  
  314.         }  
  315.         sbBuilder.append("]");  
  316.         return sbBuilder.toString();  
  317.     }  
  318.   
  319.     /** 
  320.      * 获取该二叉查找树的字符串表示 
  321.      */  
  322.     public String toString() {  
  323.         StringBuilder sbBuilder = new StringBuilder(" [ ");  
  324.         for (TreeNode p : inOrderTraverseList()) {  
  325.             sbBuilder.append(p);  
  326.             sbBuilder.append(" ");  
  327.         }  
  328.         sbBuilder.append("]");  
  329.         return sbBuilder.toString();  
  330.     }  
  331.   
  332.     public TreeNode getRoot() {  
  333.         return root;  
  334.     }  
  335.   
  336.     public static void testNode(BinarySearchTree bst, TreeNode pNode)  
  337.             throws Exception {  
  338.         System.out.println("本结点: " + pNode);  
  339.         System.out.println("前趋结点: " + bst.precessor(pNode));  
  340.         System.out.println("后继结点: " + bst.successor(pNode));  
  341.     }  
  342.   
  343.     public static void testTraverse(BinarySearchTree bst) {  
  344.         System.out.println("二叉树遍历:" + bst);  
  345.         System.out.println("二叉查找树转换为有序列表: " + bst.toStringOfOrderList());  
  346.     }  
  347.   
  348.     public static void main(String[] args) {  
  349.         try {  
  350.             BinarySearchTree bst = new BinarySearchTree();  
  351.             System.out.println("查找树是否为空? " + (bst.isEmpty() ? "是" : "否"));  
  352.             int[] keys = new int[] { 15, 6, 18, 3, 7, 13, 20, 2, 9, 4 };  
  353.             for (int key : keys) {  
  354.                 bst.insert(key);  
  355.             }  
  356.             System.out.println("查找树是否为空? " + (bst.isEmpty() ? "是" : "否"));  
  357.             TreeNode minkeyNode = bst.minElemNode(bst.getRoot());  
  358.             System.out.println("最小关键字: " + minkeyNode.getKey());  
  359.             testNode(bst, minkeyNode);  
  360.             TreeNode maxKeyNode = bst.maxElemNode(bst.getRoot());  
  361.             System.out.println("最大关键字: " + maxKeyNode.getKey());  
  362.             testNode(bst, maxKeyNode);  
  363.             System.out.println("根结点关键字: " + bst.getRoot().getKey());  
  364.             testNode(bst, bst.getRoot());  
  365.             testTraverse(bst);  
  366.             System.out.println("****************************** ");  
  367.             testTraverse(bst);  
  368.         } catch (Exception e) {  
  369.             System.out.println(e.getMessage());  
  370.             e.printStackTrace();  
  371.         }  
  372.     }  
  373.   

posted on 2015-12-10 11:59  简约不简单  阅读(145)  评论(0编辑  收藏  举报

导航