標籤:資料結構 二叉排序樹 二叉尋找樹 java二叉尋找樹
二叉尋找樹
也叫二叉排序樹。
對於樹中的每個節點X,它的所有左子樹中項的值小於X節點中的項,所有右子樹中的項的值大於X的項。
需要實現的基本操作有:
1.包含:
判斷某個元素是否包含在二叉尋找樹中,若存在則放回true,否則返回false。
具體操作步驟如下:
(1).從根結點開始進行判斷,根結點為空白則直接結束返回false;
(2).如果相等則直接結束返回true;如果大於根結點的值,則繼續與根結點的右子樹進行比較;如果小於根結點的值,則繼續與根結點的左子樹進行比較;
(3).重複第(2)步操作,直至找到相等的元素返回true或者二叉樹遍曆結束也沒找到則返回false。
2.插入:
注意在插入的時候需要判斷該元素是否存在於二叉樹中,即需要進行比較尋找操作,若存在則不插入,否則則插入。
具體操作步驟如下:
(1).從根結點開始進行判斷,根結點為空白則直接插入;
(2).如果相等則直接結束,不進行插入;如果大於根結點的值,則繼續與根結點的右子樹進行比較;如果小於根結點的值,則繼續與根結點的左子樹進行比較;
(3).一直進行第(2)步的迴圈,直至對應的結點為空白,則直接將該元素對應的結點插入在此。
3.刪除:
注意在刪除的時候需要判斷該元素是否存在於二叉樹中,即需要進行比較尋找操作,若不存在則不進行相關操作,直接返回,否則刪除對應結點,然後調整二叉尋找樹的結點位置關係,返回。
具體操作如下:
(1).從根結點開始進行判斷,若根結點為空白則直接無操作返回;
(2).如果相等則直接刪除該結點,然後進行相關結點調整,返回返回;如果大於根結點的值,則繼續與根結點的右子樹進行比較;如果小於根結點的值,則繼續與根結點的左子樹進行比較;
(3).一直進行第(2)步的迴圈,直至相等條件出現進行第(2)步前面的操作,或者直至對應的二叉樹為空白也未出現相等的值,則直接無操作返回。
注意:上述說的進行相關結點調整是這樣的,刪除結點的值為e的結點後需要找到以該結點為根結點的最小右子樹或者最大左子樹結點來替代該結點,即以該結點的前驅或者後繼來替換(前驅:是該節點的左子樹中的最大節點;後繼:是該節點的右子樹中的最小節點)。
4.最大:
根據二叉尋找樹的性質:右子樹的項比左子樹的項的值大。
從根結點開始進行遍曆,直至最右子樹結點的出現,則該結點的值為該二叉尋找樹最大值。
5.最小:
同上述尋找最大值一樣,我們只要找到最左子樹結點的值即可。
6.遍曆:
同二叉樹的遍曆一樣,可以進行前序走訪,中序遍曆,後序遍曆,層次遍曆等。
注意中序遍曆的結果為一個遞增的序列。
此外還有尋找前驅結點和後繼結點等操作。
下面是我的Java實現方法。
package com.phn.tree;/** * @author 潘海南 * @Email [email protected] * @TODO 二叉尋找樹 * @date 2015年7月27日 */public class FOBinarySearchTree<E extends Comparable<E>> { //二叉尋找樹的根結點 private FOBinaryTreeNode<E> root; /** * TODO 無參建構函式,初始化二叉排序樹 */ public FOBinarySearchTree() { this.root = null; } /** * @TODO 輸入元素e是否包含在該二叉排序樹中 * @param e 輸入元素 * @return true or false */ public boolean contains(E e) { return this.contains2(e, root); } /** * @TODO 二叉排序樹是否包含某個元素的具體實現 * @param e 輸入元素 * @param node 樹的根結點 * @return true or false */ private boolean contains2(E e, FOBinaryTreeNode<E> node) { if (node == null) return false; else { int result = e.compareTo(node.getE()); if (result < 0) { return contains2(e, node.getLeftChild()); } else if (result > 0) { return contains2(e, node.getRightChild()); } else { return true; } } } /** * @TODO 二叉排序樹尋找輸入元素在樹中的結點資訊 * @param e 輸入元素 * @return 該輸入元素在樹中的結點資訊 */ public FOBinaryTreeNode<E> search(E e) { if (root == null) { throw new RuntimeException("該樹為空白!"); } FOBinaryTreeNode<E> tempNode = root; while (tempNode != null) { int result = e.compareTo(tempNode.getE()); if (result == 0) { return tempNode; } else if (result < 0) { tempNode = tempNode.getLeftChild(); } else { tempNode = tempNode.getRightChild(); } } return null; } /** * @TODO 二叉排序樹插入元素 * @param e 需要插入的元素 * @return true or false */ public boolean add(E e) { if (root == null) { root = new FOBinaryTreeNode<E>(); root.setE(e); return true; } FOBinaryTreeNode<E> tempInsertNode = root; FOBinaryTreeNode<E> insertParentNode = new FOBinaryTreeNode<E>(); int result = 0; while (tempInsertNode != null) { insertParentNode = tempInsertNode; result = e.compareTo(tempInsertNode.getE()); if (result < 0) { tempInsertNode = tempInsertNode.getLeftChild(); } else if (result > 0) { tempInsertNode = tempInsertNode.getRightChild(); } else { return true; } } FOBinaryTreeNode<E> insertNode = new FOBinaryTreeNode<E>(); insertNode.setE(e); insertNode.setParent(insertParentNode); int cmpResult = e.compareTo(insertParentNode.getE()); if (cmpResult > 0) { insertParentNode.setRightChild(insertNode); } else { insertParentNode.setLeftChild(insertNode); } return true; } /** * @TODO 二叉排序樹刪除在數中的輸入的元素e * @param e 將要刪除的輸入元素 * @return true or false */ public boolean remove(E e) { FOBinaryTreeNode<E> removeNode = this.search(e); if (removeNode == null) { return false; } FOBinaryTreeNode<E> preRemoveNode = this.findPreNode(removeNode); if (preRemoveNode != null) { removeByPreNode(removeNode, preRemoveNode); return true; } FOBinaryTreeNode<E> nextRemoveNode = this.findNextNode(removeNode); if (nextRemoveNode != null) { removeByNextNode(removeNode, nextRemoveNode); return true; } if (removeNode.getParent().getLeftChild() == removeNode) { removeNode.getParent().setLeftChild(null); } else { removeNode.getParent().setRightChild(null); } return true; } /** * @TODO 刪除二叉排序樹中的結點後將其前驅結點替代 * @param removeNode 將要刪除的結點 * @param preRemoveNode 將要刪除的結點的前驅結點 */ private void removeByPreNode(FOBinaryTreeNode<E> removeNode, FOBinaryTreeNode<E> preRemoveNode) { if (preRemoveNode.getLeftChild() != null) { preRemoveNode.getLeftChild().setParent(preRemoveNode.getParent()); preRemoveNode.getParent().setRightChild( preRemoveNode.getLeftChild()); } else { preRemoveNode.getParent().setRightChild(null); } preRemoveNode.setParent(removeNode.getParent()); if (removeNode.getParent().getLeftChild() == removeNode) { removeNode.getParent().setLeftChild(preRemoveNode); } else { removeNode.getParent().setRightChild(preRemoveNode); } preRemoveNode.setLeftChild(removeNode.getLeftChild()); if (removeNode.getLeftChild() != null) { removeNode.getLeftChild().setParent(preRemoveNode); } preRemoveNode.setRightChild(removeNode.getRightChild()); if (removeNode.getRightChild() != null) { removeNode.getRightChild().setParent(preRemoveNode); } } /** * @TODO 刪除二叉排序樹中的結點後將其後繼結點替代 * @param removeNode 將要刪除的結點 * @param nextRemoveNode 將要刪除的結點的後繼結點 */ private void removeByNextNode(FOBinaryTreeNode<E> removeNode, FOBinaryTreeNode<E> nextRemoveNode) { if (nextRemoveNode.getRightChild() != null) { nextRemoveNode.getRightChild() .setParent(nextRemoveNode.getParent()); nextRemoveNode.getParent().setLeftChild( nextRemoveNode.getRightChild()); } else { nextRemoveNode.getParent().setLeftChild(null); } nextRemoveNode.setParent(removeNode.getParent()); if (removeNode.getParent().getLeftChild() == removeNode) { removeNode.getParent().setLeftChild(nextRemoveNode); } else { removeNode.getParent().setRightChild(nextRemoveNode); } nextRemoveNode.setLeftChild(removeNode.getLeftChild()); if (removeNode.getLeftChild() != null) { removeNode.getLeftChild().setParent(nextRemoveNode); } nextRemoveNode.setRightChild(removeNode.getRightChild()); if (removeNode.getRightChild() != null) { removeNode.getRightChild().setParent(nextRemoveNode); } } /** * @TODO 擷取輸入結點的前驅結點 * @param node 輸入的結點 * @return 輸入結點的前驅結點 */ public FOBinaryTreeNode<E> findPreNode(FOBinaryTreeNode<E> node) { if (node == null) { throw new RuntimeException("傳入結點為空白!"); } FOBinaryTreeNode<E> tempNode = node.getLeftChild(); if (tempNode == null) { // throw new RuntimeException("傳入結點無前驅節點!"); return null; } FOBinaryTreeNode<E> preNode = tempNode; tempNode = tempNode.getRightChild(); while (tempNode != null) { preNode = tempNode; tempNode = tempNode.getRightChild(); } return preNode; } /** * @TODO 擷取輸入結點的後繼結點 * @param node 輸入結點 * @return 輸入結點的後繼結點 */ public FOBinaryTreeNode<E> findNextNode(FOBinaryTreeNode<E> node) { if (node == null) { throw new RuntimeException("傳入結點為空白!"); } FOBinaryTreeNode<E> tempNode = node.getRightChild(); if (tempNode == null) { // throw new RuntimeException("傳入結點無後繼節點!"); return null; } FOBinaryTreeNode<E> nextNode = tempNode; tempNode = tempNode.getLeftChild(); while (tempNode != null) { nextNode = tempNode; tempNode = tempNode.getLeftChild(); } return nextNode; } /** * @TODO 擷取該二叉排序樹的最大元素 * @return 該二叉排序樹的最大元素 */ public E getMaxE(){ return this.getMaxE(root); } /** * @TODO 擷取輸入二叉排序樹的最大元素的具體實現 * @param node 輸入二叉排序樹的根結點 * @return 該輸入二叉排序樹的最大元素 */ private E getMaxE(FOBinaryTreeNode<E> node) { if(node ==null){ return null; } while(node.getRightChild()!=null){ node = node.getRightChild(); } return node.getE(); } /** * @TODO 擷取該二叉排序樹的最小元素 * @return 該二叉排序樹的最小元素 */ public E getMinE(){ return this.getMinE(root); } /** * @TODO 擷取輸入二叉排序樹的最小元素的具體實現 * @param node 輸入二叉排序樹的根結點 * @return 該輸入二叉排序樹的最小元素 */ private E getMinE(FOBinaryTreeNode<E> node) { if(node ==null){ return null; } while(node.getLeftChild()!=null){ node = node.getLeftChild(); } return node.getE(); } /** * @TODO 前序走訪輸出二叉排序樹中元素 * @return 二叉排序樹中元素的字串形式 */ public String preOrderPrint() { StringBuffer sb = new StringBuffer("["); this.preOrder(root, sb); sb.replace(sb.length() - 2, sb.length() - 1, "]"); return sb.toString(); } /** * @TODO 前序走訪輸出二叉排序樹中元素的具體實現 * @param node 二叉排序樹的根結點 * @param sb 將二叉排序樹中元素的遍曆結果儲存在sb中 * @return 二叉排序樹中元素的字串形式 */ private String preOrder(FOBinaryTreeNode<E> node, StringBuffer sb) { if (node != null) { sb.append(node + ", "); preOrder(node.getLeftChild(), sb); preOrder(node.getRightChild(), sb); } return sb.toString(); } /** * @TODO 中序遍曆輸出二叉排序樹中元素 * @return 二叉排序樹中元素的字串形式 */ public String inOrderPrint() { StringBuffer sb = new StringBuffer("["); this.inOrder(root, sb); sb.replace(sb.length() - 2, sb.length() - 1, "]"); return sb.toString(); } /** * @TODO 中序遍曆輸出二叉排序樹中元素的具體實現 * @param node 二叉排序樹的根結點 * @param sb 將二叉排序樹中元素的遍曆結果儲存在sb中 * @return 二叉排序樹中元素的字串形式 */ private String inOrder(FOBinaryTreeNode<E> node, StringBuffer sb) { if (node != null) { inOrder(node.getLeftChild(), sb); sb.append(node + ", "); inOrder(node.getRightChild(), sb); } return sb.toString(); } /** * @TODO 後序遍曆輸出二叉排序樹中元素 * @return 二叉排序樹中元素的字串形式 */ public String postOrderPrint() { StringBuffer sb = new StringBuffer("["); this.postOrder(root, sb); sb.replace(sb.length() - 2, sb.length() - 1, "]"); return sb.toString(); } /** * @TODO 中序遍曆輸出二叉排序樹中元素的具體實現 * @param node 二叉排序樹的根結點 * @param sb 將二叉排序樹中元素的遍曆結果儲存在sb中 * @return 二叉排序樹中元素的字串形式 */ private String postOrder(FOBinaryTreeNode<E> node, StringBuffer sb) { if (node != null) { postOrder(node.getLeftChild(), sb); postOrder(node.getRightChild(), sb); sb.append(node + ", "); } return sb.toString(); }}
二叉樹的結點類:
package com.phn.tree;/** * @author 潘海南 * @Email [email protected] * @TODO 二叉樹結點 * @date 2015年7月27日 */public class FOBinaryTreeNode<E extends Comparable<E>>{ private E e ; private FOBinaryTreeNode<E> parent; private FOBinaryTreeNode<E> leftChild; private FOBinaryTreeNode<E> rightChild; public FOBinaryTreeNode() { super(); } /** * @param e * @param parent * @param leftChild * @param rightChild */ public FOBinaryTreeNode(E e, FOBinaryTreeNode<E> parent, FOBinaryTreeNode<E> leftChild, FOBinaryTreeNode<E> rightChild) { super(); this.e = e; this.parent = parent; this.leftChild = leftChild; this.rightChild = rightChild; } public E getE() { return e; } public void setE(E e) { this.e = e; } public FOBinaryTreeNode<E> getParent() { return parent; } public void setParent(FOBinaryTreeNode<E> parent) { this.parent = parent; } public FOBinaryTreeNode<E> getLeftChild() { return leftChild; } public void setLeftChild(FOBinaryTreeNode<E> leftChild) { this.leftChild = leftChild; } public FOBinaryTreeNode<E> getRightChild() { return rightChild; } public void setRightChild(FOBinaryTreeNode<E> rightChild) { this.rightChild = rightChild; } @Override public String toString() { return e.toString(); }}
測試代碼:
package com.phn.tree;/** * @author 潘海南 * @Email [email protected] * @TODO * @date 2015年7月29日 */public class FOBinarySearchTreeTest { public static void main(String[] args) { FOBinarySearchTree<String> fobst = new FOBinarySearchTree<String>(); fobst.add("f"); fobst.add("e"); fobst.add("b"); fobst.add("a"); fobst.add("d"); fobst.add("c"); fobst.add("i"); fobst.add("g"); fobst.add("h"); fobst.add("j"); System.out.println(fobst.preOrderPrint()); System.out.println(fobst.inOrderPrint()); System.out.println(fobst.postOrderPrint()); System.out.println(fobst.contains("a")); System.out.println(fobst.contains("v")); System.out.println(fobst.remove("a")); System.out.println(fobst.preOrderPrint()); System.out.println(fobst.inOrderPrint()); System.out.println(fobst.postOrderPrint()); System.out.println(fobst.remove("e")); System.out.println(fobst.preOrderPrint()); System.out.println(fobst.inOrderPrint()); System.out.println(fobst.postOrderPrint()); System.out.println(fobst.remove("k")); System.out.println(fobst.preOrderPrint()); System.out.println(fobst.inOrderPrint()); System.out.println(fobst.postOrderPrint()); System.out.println(fobst.getMaxE()); System.out.println(fobst.getMinE()); }}
測試結果:
著作權聲明:本文為博主原創文章,如需轉載請註明出處並附上連結,謝謝。
Java資料結構-樹的應用-二叉尋找樹