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