由前面兩講,我們已經對二叉樹有所瞭解了,這一次我們來講一個特殊的二叉樹,即二叉排序樹,也稱二叉尋找樹。
二叉排序樹滿足如下條件:
(1)是二叉樹;
(2)對於每一個節點P來說,若其左子樹不為空白,則其左子樹的各節點的值都小於節點P的值,若其右子樹不為空白,則其右子樹中所有節點的值都大於節點P的值。
接下來我們使用JAVA語言實現二叉排序樹,僅列出插入和刪除函數的實現方式。
package mianshiti;import java.util.*;public class BinarySearchTree {private TreeNode root=null;//根節點public static void main(String[] args) {// TODO Auto-generated method stubBinarySearchTree mytree=new BinarySearchTree();mytree.insert(4);mytree.insert(2);mytree.insert(6);mytree.insert(1);mytree.insert(3);mytree.insert(5);mytree.insert(8);mytree.insert(7);mytree.delete(4);//BinarySearchTree<Character> tree=new BinarySearchTree<Character>(init());System.out.println("遞迴方式實現前序走訪:");mytree.preorder(mytree.getRoot());System.out.println();System.out.println("遞迴方式實現中序遍曆:");mytree.inorder(mytree.getRoot());System.out.println();System.out.println("遞迴方式實現後序遍曆:");mytree.postorder(mytree.getRoot());System.out.println();System.out.println("非遞迴方式實現前序走訪:");mytree.nonRecursivePreorder(mytree.getRoot());System.out.println();System.out.println("非遞迴方式實現中序遍曆:");mytree.nonRecursiveInorder(mytree.getRoot());System.out.println();System.out.println("非遞迴方式實現後序遍曆:");mytree.nonRecursivePostorder(mytree.getRoot());System.out.println();}//前序走訪public void preorder(TreeNode node){if(node!=null){this.getNodeInfo(node);preorder(node.left);preorder(node.right);}}//中序遍曆public void inorder(TreeNode node){if(node!=null){inorder(node.left);this.getNodeInfo(node);inorder(node.right);}}//後序遍曆public void postorder(TreeNode node){if(node!=null){postorder(node.left);postorder(node.right);this.getNodeInfo(node);}}//非遞迴方式實現前序走訪public void nonRecursivePreorder(TreeNode node){Stack<TreeNode> mystack=new Stack<TreeNode>();if(node!=null){mystack.push(node);while(!mystack.isEmpty()){TreeNode temp=mystack.pop();this.getNodeInfo(temp);if(temp.right!=null){mystack.push(temp.right);}if(temp.left!=null){mystack.push(temp.left);}}}}//非遞迴方式實現中序遍曆public void nonRecursiveInorder(TreeNode node){Stack<TreeNode> mystack=new Stack<TreeNode>();while(node!=null){while(node!=null){if(node.right!=null){mystack.push(node.right);}mystack.push(node);node=node.left;}node=mystack.pop();while(!mystack.isEmpty()&&node.right==null){this.getNodeInfo(node);node=mystack.pop();}this.getNodeInfo(node);if(!mystack.isEmpty()){node=mystack.pop();}else{node=null;}}}//非遞迴方式實現後續遍曆public void nonRecursivePostorder(TreeNode node){Stack<TreeNode> mystack=new Stack<TreeNode>();TreeNode temp=node;while(node!=null){for(;node.left!=null;node=node.left){mystack.push(node);}while(node!=null&&(node.right==null||node.right==temp)){this.getNodeInfo(node);temp=node;if(mystack.isEmpty())return;node=mystack.pop();}mystack.push(node);node=node.right;}}//建構函式public BinarySearchTree(){this.root=null;}public TreeNode getRoot(){return this.root;}//添加一個節點public void insert(int value){TreeNode nextnode=new TreeNode(value);TreeNode temp=this.root;if(this.root==null){this.root=nextnode;nextnode.parent=null;return ;}while(temp!=null){if(value<temp.data){if(temp.left==null){temp.left=nextnode;nextnode.parent=temp;return;}else{temp=temp.left;}}else if(value>temp.data){if(temp.right==null){temp.right=nextnode;nextnode.parent=temp;return;}else{temp=temp.right;}}}}//擷取以begin為根節點的樹的最小關鍵字節點的引用private TreeNode minTreeNode(TreeNode begin){if(begin==null)return null;while(begin.left!=null){begin=begin.left;}return begin;}//擷取以begin為根節點的樹的最大關鍵字節點的引用private TreeNode maxTreeNode(TreeNode begin){if(begin==null)return null;while(begin.right!=null){begin=begin.right;}return begin;}//刪除一個節點public void delete(int value){if(this.root==null){System.out.println("樹為空白,無法刪除"+value);return;}TreeNode temp=this.root;while(temp!=null){if(value>temp.data){if(temp.right==null){System.out.println("樹中沒有要刪除的項");}else{temp=temp.right;}}else if(value<temp.data){if(temp.left==null){System.out.println("樹中沒有要刪除的項");}else{temp=temp.left;}}else{//找到了這個節點if(temp.left==null&&temp.right==null)//該節點是分葉節點{if(temp.parent.right==temp){temp.parent.right=null;}else{temp.parent.left=null;}}else if(temp.right!=null&&temp.left==null)//左子樹為空白,右子樹不為空白{if(temp.parent.right==temp){temp.parent.right=temp.right;temp.right.parent=temp.parent;}else{temp.parent.left=temp.right;temp.right.parent=temp.parent;}}else if(temp.left!=null&&temp.right==null)//左子樹不為空白,右子樹為空白{if(temp.parent.right==temp){temp.parent.right=temp.left;temp.left.parent=temp.parent;}else{temp.parent.left=temp.left;temp.left.parent=temp.parent;}}else//左右子樹都不為空白{TreeNode replacenode=minTreeNode(temp.right);delete(replacenode.data);temp.data=replacenode.data;}break;}}}public void getNodeInfo(TreeNode treenode){if(treenode!=null){System.out.print(treenode.data+" ");}}}class TreeNode{public int data;public TreeNode left;//左子節點public TreeNode right;//右子節點public TreeNode parent;//父節點//建構函式public TreeNode(int data){this(data,null,null,null);}public TreeNode(int data,TreeNode left,TreeNode right,TreeNode parent){this.data=data;this.left=left;this.right=right;this.parent=parent;}}
運行結果如下所示:
遞迴方式實現前序走訪:5 2 1 3 6 8 7 遞迴方式實現中序遍曆:1 2 3 5 6 7 8 遞迴方式實現後序遍曆:1 3 2 7 8 6 5 非遞迴方式實現前序走訪:5 2 1 3 6 8 7 非遞迴方式實現中序遍曆:1 2 3 5 6 7 8 非遞迴方式實現後序遍曆:1 3 2 7 8 6 5