手寫二叉排序樹(查詢樹、搜尋樹)
阿新 • • 發佈:2018-12-30
二叉排序樹(查詢樹,搜尋樹)或者是一顆空樹,或者是一顆具有如下性質的樹:
1)若左子樹不為空,那麼左子樹上面的所有節點的關鍵字值都比根節點的關鍵字值小
2)若右子樹不為空,那麼右子樹上面的所有節點的關鍵字值都比根節點的關鍵字值大
3)左右子樹都為二叉樹
4)沒有重複值(這一點在實際中可以忽略)
public class SearchBinaryTree { //根節點 public TreeNode root; /** * 新增節點 */ public TreeNode put(int data) { TreeNode newNode = new TreeNode(data); if (root == null) { root = newNode; return newNode; } TreeNode treeNode = root; TreeNode parent = null; while (treeNode != null) { parent = treeNode; if (data < treeNode.data) { treeNode = treeNode.leftChild; } else if (data > treeNode.data) { treeNode = treeNode.rightChild; } else {//相等情況不考慮 不插入 return treeNode; } } newNode.parent = parent; if (data < parent.data) { parent.leftChild = newNode; } else { parent.rightChild = newNode; } return newNode; } /** * 查詢節點 */ public TreeNode search(int data) { if (root == null) { return null; } TreeNode node = root; while (node != null) { if (data < node.data) { node = node.leftChild; } else if (data > node.data) { node = node.rightChild; } else { return node; } } return null; } /** * 刪除節點 */ public void deleteNode(TreeNode node) { if (node == null) { throw new NoSuchElementException(); } else { //先得到父親 TreeNode parent = node.parent; //1.是葉子 if (node.leftChild == null && node.rightChild == null) { //特別情況 1.樹上只有一個節點 或者空樹 if (parent == null) { root = null; } else if (parent.leftChild == node) { parent.leftChild = null; } else { parent.rightChild = null; } node.parent = null; } else if (node.leftChild != null && node.rightChild == null) { //只有左孩子 if (parent==null){//是根節點 node.leftChild.parent=null; root=node.leftChild; }else { if (node==parent.leftChild){//要刪除的節點在父親左邊 parent.leftChild=node.leftChild; }else {//要刪除節點在父親右邊 parent.rightChild=parent.leftChild; } node.leftChild.parent=parent; } node.parent=null; node.leftChild=null; } else if (node.leftChild == null && node.rightChild != null) { //只有右孩子 if (parent==null){//是根節點 node.rightChild.parent=null; root=node.rightChild; }else { node.rightChild.parent=parent; if (node==parent.leftChild){//要刪除的節點在父親左邊 parent.leftChild=node.rightChild; }else {//要刪除節點在父親右邊 parent.rightChild=node.rightChild; } } node.parent=null; node.rightChild=null; } else {//有左右兩個孩子 if (node.rightChild.leftChild==null){//如果右子樹的左子樹為空 就直接補上右子樹 node.rightChild.leftChild=node.leftChild; node.leftChild.parent=node.rightChild; if (parent==null){ root=node.rightChild; }else { if (parent.leftChild==node){ parent.leftChild=node.rightChild; node.rightChild.parent=parent; }else { parent.rightChild=node.rightChild; node.rightChild.parent=parent; } } }else {//否則就補上右子樹的左子樹上最小的一個 TreeNode leftNode=getMinLeftTreeNode(node.rightChild); leftNode.leftChild=node.leftChild; node.leftChild.parent=leftNode; if (parent==null){ root=node.rightChild; }else { if (parent.leftChild==node){ parent.leftChild=node.rightChild; node.rightChild.parent=parent; }else { parent.rightChild=node.rightChild; node.rightChild.parent=parent; } } } node.parent=null; node.rightChild=null; node.leftChild=null; } } } private TreeNode getMinLeftTreeNode(TreeNode node) { TreeNode curRoot=null; if (node==null){ return null; }else { curRoot=node; while (curRoot.leftChild!=null){ curRoot=curRoot.leftChild; } } return curRoot; } /** * 中序遍歷 */ public void midOrderTraverse(TreeNode root) { if (root == null) { return; } //LDR midOrderTraverse(root.leftChild); System.out.print(root.data + " "); midOrderTraverse(root.rightChild); } public static class TreeNode { int data; TreeNode leftChild; TreeNode rightChild; TreeNode parent; public TreeNode(int data) { this.data = data; this.leftChild = null; this.rightChild = null; this.parent = null; } } }
測試結果
/* 5 2 8 1 4 6 9 3 7 */ @Test public void testBinaryTree(){ int[] array={5,2,8,6,8,5,9,4,1,7,3,9}; SearchBinaryTree searchBinaryTree=new SearchBinaryTree(); for (int i:array){ searchBinaryTree.put(i); } searchBinaryTree.midOrderTraverse(searchBinaryTree.root); System.out.println(); System.out.println(searchBinaryTree.search(8).data); SearchBinaryTree.TreeNode node=searchBinaryTree.search(5); searchBinaryTree.deleteNode(node); System.out.println(); searchBinaryTree.midOrderTraverse(searchBinaryTree.root); }
列印結果看是正確的
1 2 3 4 5 6 7 8 9
8
1 2 3 4 6 7 8 9