二叉查找树Java实现代码
生活随笔
收集整理的這篇文章主要介紹了
二叉查找树Java实现代码
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
二叉查找樹(Binary Search Tree),或者是一顆空樹,或者是具有下列性質的二叉樹:
1、若它的左子樹不空,則其左子樹上的所有結點的值均小于它根結點的值;
2、若它的右子樹不空,則其右子樹上的所有結點的值均大于它根結點的值;
1、若它的左子樹不空,則其左子樹上的所有結點的值均小于它根結點的值;
2、若它的右子樹不空,則其右子樹上的所有結點的值均大于它根結點的值;
3、它的左、右子樹也分別為二叉查找樹。
實現(xiàn)代碼如下:重點是理解插入和刪除后樹的重新調整
package cn.hm;/** * @author fjssharpsword 2016-7-20 * 實現(xiàn)一個二叉查找樹的功能,可以進行動態(tài)插入、刪除關鍵字; * 查詢給定關鍵字、最小關鍵字、最大關鍵字;轉換為有序列表(用于排序) */ import java.util.ArrayList; import java.util.List; public class BinarySearchTree { // 樹的根結點 private TreeNode root = null; // 遍歷結點列表 private List<TreeNode> nodelist = new ArrayList<TreeNode>(); //定義樹結構private class TreeNode { private int key; private TreeNode leftChild; private TreeNode rightChild; private TreeNode parent; public TreeNode(int key, TreeNode leftChild, TreeNode rightChild, TreeNode parent) { this.key = key; this.leftChild = leftChild; this.rightChild = rightChild; this.parent = parent; } public int getKey() { return key; } public String toString() { String leftkey = (leftChild == null ? "" : String.valueOf(leftChild.key)); String rightkey = (rightChild == null ? "" : String .valueOf(rightChild.key)); return "(" + leftkey + " , " + key + " , " + rightkey + ")"; } } /** * isEmpty: 判斷二叉查找樹是否為空;若為空,返回 true ,否則返回 false . * */ public boolean isEmpty() { if (root == null) { return true; } else { return false; } } /** * TreeEmpty: 對于某些二叉查找樹操作(比如刪除關鍵字)來說,若樹為空,則拋出異常。 */ public void TreeEmpty() throws Exception { if (isEmpty()) { throw new Exception("樹為空!"); } } /** * search: 在二叉查找樹中查詢給定關鍵字 * * @param key 給定關鍵字 * @return 匹配給定關鍵字的樹結點 */ public TreeNode search(int key) { TreeNode pNode = root; while (pNode != null && pNode.key != key) { if (key < pNode.key) { pNode = pNode.leftChild; } else { pNode = pNode.rightChild; } } return pNode; } /** * minElemNode: 獲取二叉查找樹中的最小關鍵字結點 * * @return 二叉查找樹的最小關鍵字結點 ,一直向左* @throws Exception 若樹為空,則拋出異常 */ public TreeNode minElemNode(TreeNode node) throws Exception { if (node == null) { throw new Exception("樹為空!"); } TreeNode pNode = node; while (pNode.leftChild != null) { pNode = pNode.leftChild; } return pNode; } /** * maxElemNode: 獲取二叉查找樹中的最大關鍵字結點 * * @return 二叉查找樹的最大關鍵字結點 ,一直向右* @throws Exception 若樹為空,則拋出異常 */ public TreeNode maxElemNode(TreeNode node) throws Exception { if (node == null) { throw new Exception("樹為空!"); } TreeNode pNode = node; while (pNode.rightChild != null) { pNode = pNode.rightChild; } return pNode; } /** * successor: 獲取給定結點在中序遍歷順序下的后繼結點 * @param node 給定樹中的結點 * @return 若該結點存在中序遍歷順序下的后繼結點,則返回其后繼結點;否則返回 null * @throws Exception */ public TreeNode successor(TreeNode node) throws Exception { if (node == null) { return null; } // 若該結點的右子樹不為空,則其后繼結點就是右子樹中的最小關鍵字結點 if (node.rightChild != null) { return minElemNode(node.rightChild); } // 若該結點右子樹為空 TreeNode parentNode = node.parent; while (parentNode != null && node == parentNode.rightChild) { node = parentNode; parentNode = parentNode.parent; } return parentNode; } /** * precessor: 獲取給定結點在中序遍歷順序下的前趨結點 * @param node 給定樹中的結點 * @return 若該結點存在中序遍歷順序下的前趨結點,則返回其前趨結點;否則返回 null * @throws Exception */ public TreeNode precessor(TreeNode node) throws Exception { if (node == null) { return null; } // 若該結點的左子樹不為空,則其前趨結點就是左子樹中的最大關鍵字結點 if (node.leftChild != null) { return maxElemNode(node.leftChild); } // 若該結點左子樹為空 TreeNode parentNode = node.parent; while (parentNode != null && node == parentNode.leftChild) { node = parentNode; parentNode = parentNode.parent; } return parentNode; } /** * insert: 將給定關鍵字插入到二叉查找樹中 * 插入后要調整二叉查找樹左小右大結構* @param key 給定關鍵字 */ public void insert(int key) { TreeNode parentNode = null; TreeNode newNode = new TreeNode(key, null, null, null); TreeNode pNode = root; if (root == null) { root = newNode; return; } while (pNode != null) { parentNode = pNode; if (key < pNode.key) { pNode = pNode.leftChild; } else if (key > pNode.key) { pNode = pNode.rightChild; } else { // 樹中已存在匹配給定關鍵字的結點,則什么都不做直接返回 return; } } if (key < parentNode.key) { parentNode.leftChild = newNode; newNode.parent = parentNode; } else { parentNode.rightChild = newNode; newNode.parent = parentNode; } } /** * delete: 從二叉查找樹中刪除匹配給定關鍵字相應的樹結點 * * @param key 給定關鍵字 */ public void delete(int key) throws Exception { TreeNode pNode = search(key); if (pNode == null) { throw new Exception("樹中不存在要刪除的關鍵字!"); } delete(pNode); } /** * delete: 從二叉查找樹中刪除給定的結點. * * @param pNode 要刪除的結點 前置條件: 給定結點在二叉查找樹中已經(jīng)存在 * 刪除后要調整二叉查找樹,滿足左小右大結構* @throws Exception */ private void delete(TreeNode pNode) throws Exception { if (pNode == null) { return; } if (pNode.leftChild == null && pNode.rightChild == null) { // 該結點既無左孩子結點,也無右孩子結點 TreeNode parentNode = pNode.parent; if (pNode == parentNode.leftChild) { parentNode.leftChild = null; } else { parentNode.rightChild = null; } pNode=null;return; } if (pNode.leftChild == null && pNode.rightChild != null) { // 該結點左孩子結點為空,右孩子結點非空 TreeNode parentNode = pNode.parent; TreeNode rightNode=pNode.rightChild;if (pNode == parentNode.leftChild) { rightNode.parent = parentNode; parentNode.leftChild = rightNode; } else { rightNode.parent = parentNode; parentNode.rightChild = rightNode; } pNode=null;return; } if (pNode.leftChild != null && pNode.rightChild == null) { // 該結點左孩子結點非空,右孩子結點為空 TreeNode parentNode = pNode.parent; TreeNode leftNode=pNode.leftChild;if (pNode == parentNode.leftChild) {leftNode.parent = parentNode;parentNode.leftChild = leftNode; } else { leftNode.parent = parentNode;parentNode.rightChild = leftNode; } pNode=null;return; } if(pNode.leftChild != null && pNode.rightChild != null){// 該結點左右孩子結點均非空TreeNode successorNode = successor(pNode); pNode.key = successorNode.key; delete(successorNode); }} /** * inOrderTraverseList: 獲得二叉查找樹的中序遍歷結點列表 * * @return 二叉查找樹的中序遍歷結點列表 */ public List<TreeNode> inOrderTraverseList() { if (nodelist != null) { nodelist.clear(); } inOrderTraverse(root); return nodelist; } /** * inOrderTraverse: 對給定二叉查找樹進行中序遍歷 * * @param root 給定二叉查找樹的根結點 */ private void inOrderTraverse(TreeNode root) { if (root != null) { inOrderTraverse(root.leftChild); nodelist.add(root); inOrderTraverse(root.rightChild); } } /** * toStringOfOrderList: 獲取二叉查找樹中關鍵字的有序列表 * * @return 二叉查找樹中關鍵字的有序列表 */ public String toStringOfOrderList() { StringBuilder sbBuilder = new StringBuilder(" [ "); for (TreeNode p : inOrderTraverseList()) { sbBuilder.append(p.key); sbBuilder.append(" "); } sbBuilder.append("]"); return sbBuilder.toString(); } /** * 獲取該二叉查找樹的字符串表示 */ public String toString() { StringBuilder sbBuilder = new StringBuilder(" [ "); for (TreeNode p : inOrderTraverseList()) { sbBuilder.append(p.toString()); sbBuilder.append(" "); } sbBuilder.append("]"); return sbBuilder.toString(); } public TreeNode getRoot() { return root; } public static void testNode(BinarySearchTree bst, TreeNode pNode) throws Exception { System.out.println("本結點: " + pNode); System.out.println("前趨結點: " + bst.precessor(pNode)); System.out.println("后繼結點: " + bst.successor(pNode)); } public static void testTraverse(BinarySearchTree bst) { System.out.println("二叉樹遍歷:" + bst.toString()); System.out.println("二叉查找樹轉換為有序列表: " + bst.toStringOfOrderList()); } public static void main(String[] args) { try { BinarySearchTree bst = new BinarySearchTree(); //插入System.out.println("查找樹是否為空? " + (bst.isEmpty() ? "是" : "否")); int[] keys = new int[] { 52,18,69,32,10,2,7,72,86,98,100,5,1020,789,13,15 }; for (int key : keys) { bst.insert(key); } System.out.println("查找樹是否為空? " + (bst.isEmpty() ? "是" : "否")); //找最小結點TreeNode minkeyNode = bst.minElemNode(bst.getRoot()); System.out.println("最小關鍵字: " + minkeyNode.getKey()); testNode(bst, minkeyNode); //找最大結點TreeNode maxKeyNode = bst.maxElemNode(bst.getRoot()); System.out.println("最大關鍵字: " + maxKeyNode.getKey()); testNode(bst, maxKeyNode); //根結點System.out.println("根結點關鍵字: " + bst.getRoot().getKey()); testNode(bst, bst.getRoot()); //遍歷二叉樹testTraverse(bst); //刪除一個結點bst.delete(100); testTraverse(bst); } catch (Exception e) { System.out.println(e.getMessage()); e.printStackTrace(); } } } 執(zhí)行結果如下: 查找樹是否為空? 是 查找樹是否為空? 否 最小關鍵字: 2 本結點: ( , 2 , 7) 前趨結點: null 后繼結點: ( , 5 , ) 最大關鍵字: 1020 本結點: (789 , 1020 , ) 前趨結點: ( , 789 , ) 后繼結點: null 根結點關鍵字: 52 本結點: (18 , 52 , 69) 前趨結點: ( , 32 , ) 后繼結點: ( , 69 , 72) 二叉樹遍歷: [ ( , 2 , 7) ( , 5 , ) (5 , 7 , ) (2 , 10 , 13) ( , 13 , 15) ( , 15 , ) (10 , 18 , 32) ( , 32 , ) (18 , 52 , 69) ( , 69 , 72) ( , 72 , 86) ( , 86 , 98) ( , 98 , 100) ( , 100 , 1020) ( , 789 , ) (789 , 1020 , ) ] 二叉查找樹轉換為有序列表: [ 2 5 7 10 13 15 18 32 52 69 72 86 98 100 789 1020 ] 二叉樹遍歷: [ ( , 2 , 7) ( , 5 , ) (5 , 7 , ) (2 , 10 , 13) ( , 13 , 15) ( , 15 , ) (10 , 18 , 32) ( , 32 , ) (18 , 52 , 69) ( , 69 , 72) ( , 72 , 86) ( , 86 , 98) ( , 98 , 1020) ( , 789 , ) (789 , 1020 , ) ] 二叉查找樹轉換為有序列表: [ 2 5 7 10 13 15 18 32 52 69 72 86 98 789 1020 ]總結
以上是生活随笔為你收集整理的二叉查找树Java实现代码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java工程中使用Log4j小记
- 下一篇: Java工程中引用Base64编码解码小