标题写的是TreeSet,但是在此之前我先需要实现一个红黑树。
为此,这里写一些篇幅实现搜索树。包括二叉搜索树、AVL、红黑树。
每个树都实现增加删除等功能。
这篇先讲二叉搜索树。
二叉搜索树的基本结构就是一颗二叉树。它的特点就是对于一个节点s,它的左子树的所有节点的key都小于s节点的key值,它的右子树的所有节点的key值都大于s的key值。
注意:s节点是任意的,也就是说,对于任意一个节点s都需要满足这个条件。
在实现二叉树中,删除操作是最难的。我也是去网上看了一些人的解释才弄明白一点。我理解到的要点就是:删除一个节点,该节点有以下三种情况:
1)无孩子,是一个叶子节点; 2)只有一个孩子; 3)有两个孩子。
(这里的孩子说的是直接后代,也就是说这个孩子是什么情况不讨论)
然后对于情况1)直接删除就行,需要处理它的父节点;情况2)将它的父节点指向它的孩子;情况3)从他的所有子代中找一个前驱或者后继节点进行替换,然后删除前驱(这个可能会比较难理解)
前驱和后继的概念就是将这颗二叉树用前序遍历进行输出,前驱就是这个节点的直接前面节点,后继就是这个节点的直接后面的节点。(我这里是找他的前驱节点,也就是右子树中最小值)
前驱(右子树(保证比他大)最小值(直接前驱))
后继(左子树(保证比他小)最大值(直接后继))
将该节点指向它的前驱,然后在它的右子树中删除树中最小值。维持二叉搜索树的特点
代码:
public class HBSTree<K extends Comparable<K>, V> {private TreeNode root;private final class TreeNode{private K key;private V val;private TreeNode lChild;private TreeNode rChild;TreeNode(K key, V val){this.key = key;this.val = val;lChild = null;rChild = null;}}HBSTree(){root = null;}public void insert(K key, V val){if(key == null) return ;if(val == null) return ;root = insert(root, key, val);}private TreeNode insert(TreeNode treeNode, K key, V val){if(treeNode == null)treeNode = new TreeNode(key, val);int cmp = key.compareTo(treeNode.key);if (cmp < 0) treeNode.lChild = insert(treeNode.lChild, key, val);else if (cmp > 0) treeNode.rChild = insert(treeNode.rChild, key, val);else treeNode.val = val;return treeNode;}public boolean contains(K key){if(key == null) return false;return get(root, key) != null;}public V get(K key){TreeNode treeNode = get(root, key);if(treeNode == null) return null;return treeNode.val;}private TreeNode get(TreeNode treeNode, K key){if(treeNode == null) return null;int cmp = key.compareTo(treeNode.key);if (cmp < 0) return get(treeNode.lChild, key);else if (cmp > 0) return get(treeNode.rChild, key);else return treeNode;}public K minKey(){if(root == null) return null;return minKey(root).key;}/*** recursive way to implement minKey* private TreeNode minKey(TreeNode treeNode){* if(treeNode.lChild == null) return treeNode;* return minKey(treeNode.lChild);* }*/private TreeNode minKey(TreeNode treeNode){if(treeNode == null) return null;while (treeNode.lChild != null) treeNode = treeNode.lChild;return treeNode;}public K maxKey(){if(root == null) return null;return maxKey(root).key;}/*** recursive to implement maxKey* private TreeNode maxKey(TreeNode treeNode){* if(treeNode.rChild == null) return treeNode;* return maxKey(treeNode.rChild);* }*/private TreeNode maxKey(TreeNode treeNode){if(treeNode == null) return null;while (treeNode.rChild != null) treeNode = treeNode.rChild;return treeNode;}public void deleteMin(){if(root == null) return ;root = deleteMin(root);}private TreeNode deleteMin(TreeNode treeNode){if(treeNode.lChild == null) return treeNode.rChild;treeNode.lChild = deleteMin(treeNode.lChild);return treeNode;}public void deleteMax(){if(root == null) return ;root = deleteMax(root);}private TreeNode deleteMax(TreeNode treeNode){if(treeNode.rChild == null) return treeNode.lChild;treeNode.rChild = deleteMax(treeNode.rChild);return treeNode;}public void remove(K key){if(key == null) return ;root = remove(root, key);}private TreeNode remove(TreeNode treeNode, K key){if(treeNode == null) return null;int cmp = key.compareTo(treeNode.key);if (cmp < 0) return remove(treeNode.lChild, key);else if (cmp > 0) return remove(treeNode.rChild, key);else {if(treeNode.rChild == null) return treeNode.lChild;if(treeNode.lChild == null) return treeNode.rChild;TreeNode node = treeNode;treeNode = minKey(node.rChild);treeNode.rChild = deleteMin(node.rChild);treeNode.lChild = node.lChild;}return treeNode;}
}
最后的最后:代码很多是用递归实现。不得不承认,实现二叉树的某些方法时,的确用递归很方便而且代码简单。但是有些时候最好还是尽力去消除递归。