├── JDK源码剖析之红黑树TreeMap.pptx ├── README.md └── JDK_RBT ├── bin ├── rbt │ ├── TestRBT.class │ ├── TestAVLVSRBT.class │ └── ReflectUtilForTreeMap.class ├── bstAVL │ ├── AVLMap.class │ ├── Person.class │ ├── AVLEntry.class │ ├── TestBST$1.class │ ├── TestBST.class │ ├── AVLIterator.class │ ├── BSTIterator.class │ ├── LeetCodeAVL.class │ ├── TestBSTVSTreeMap.class │ ├── InorderSuccessorInBST.class │ └── ConvertSortedArrayToBinarySearchTree.class └── warmUp │ ├── TreeNode.class │ ├── TestLinkedList.class │ └── InvertBinaryTree.class ├── .settings ├── org.eclipse.core.resources.prefs └── org.eclipse.jdt.core.prefs ├── src ├── bstAVL │ ├── Person.java │ ├── BSTIterator.java │ ├── AVLIterator.java │ ├── AVLEntry.java │ ├── InorderSuccessorInBST.java │ ├── TestBSTVSTreeMap.java │ ├── ConvertSortedArrayToBinarySearchTree.java │ ├── TestBST.java │ └── AVLMap.java ├── warmUp │ ├── TestLinkedList.java │ ├── TreeNode.java │ └── InvertBinaryTree.java └── rbt │ ├── TestAVLVSRBT.java │ ├── ReflectUtilForTreeMap.java │ └── TestRBT.java ├── .classpath └── .project /JDK源码剖析之红黑树TreeMap.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosoraYintai/TreeMapSourceAnalysis/HEAD/JDK源码剖析之红黑树TreeMap.pptx -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TreeMapSourceAnalysis 2 | JDK源码剖析与实战之-红黑树TreeMap 3 | 4 | B站视频地址:https://www.bilibili.com/video/av23890827 5 | -------------------------------------------------------------------------------- /JDK_RBT/bin/rbt/TestRBT.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosoraYintai/TreeMapSourceAnalysis/HEAD/JDK_RBT/bin/rbt/TestRBT.class -------------------------------------------------------------------------------- /JDK_RBT/bin/bstAVL/AVLMap.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosoraYintai/TreeMapSourceAnalysis/HEAD/JDK_RBT/bin/bstAVL/AVLMap.class -------------------------------------------------------------------------------- /JDK_RBT/bin/bstAVL/Person.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosoraYintai/TreeMapSourceAnalysis/HEAD/JDK_RBT/bin/bstAVL/Person.class -------------------------------------------------------------------------------- /JDK_RBT/bin/bstAVL/AVLEntry.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosoraYintai/TreeMapSourceAnalysis/HEAD/JDK_RBT/bin/bstAVL/AVLEntry.class -------------------------------------------------------------------------------- /JDK_RBT/bin/bstAVL/TestBST$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosoraYintai/TreeMapSourceAnalysis/HEAD/JDK_RBT/bin/bstAVL/TestBST$1.class -------------------------------------------------------------------------------- /JDK_RBT/bin/bstAVL/TestBST.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosoraYintai/TreeMapSourceAnalysis/HEAD/JDK_RBT/bin/bstAVL/TestBST.class -------------------------------------------------------------------------------- /JDK_RBT/bin/rbt/TestAVLVSRBT.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosoraYintai/TreeMapSourceAnalysis/HEAD/JDK_RBT/bin/rbt/TestAVLVSRBT.class -------------------------------------------------------------------------------- /JDK_RBT/bin/warmUp/TreeNode.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosoraYintai/TreeMapSourceAnalysis/HEAD/JDK_RBT/bin/warmUp/TreeNode.class -------------------------------------------------------------------------------- /JDK_RBT/bin/bstAVL/AVLIterator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosoraYintai/TreeMapSourceAnalysis/HEAD/JDK_RBT/bin/bstAVL/AVLIterator.class -------------------------------------------------------------------------------- /JDK_RBT/bin/bstAVL/BSTIterator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosoraYintai/TreeMapSourceAnalysis/HEAD/JDK_RBT/bin/bstAVL/BSTIterator.class -------------------------------------------------------------------------------- /JDK_RBT/bin/bstAVL/LeetCodeAVL.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosoraYintai/TreeMapSourceAnalysis/HEAD/JDK_RBT/bin/bstAVL/LeetCodeAVL.class -------------------------------------------------------------------------------- /JDK_RBT/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | #Mon Apr 30 19:45:33 CST 2018 2 | eclipse.preferences.version=1 3 | encoding/=UTF-8 4 | -------------------------------------------------------------------------------- /JDK_RBT/bin/warmUp/TestLinkedList.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosoraYintai/TreeMapSourceAnalysis/HEAD/JDK_RBT/bin/warmUp/TestLinkedList.class -------------------------------------------------------------------------------- /JDK_RBT/bin/bstAVL/TestBSTVSTreeMap.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosoraYintai/TreeMapSourceAnalysis/HEAD/JDK_RBT/bin/bstAVL/TestBSTVSTreeMap.class -------------------------------------------------------------------------------- /JDK_RBT/bin/warmUp/InvertBinaryTree.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosoraYintai/TreeMapSourceAnalysis/HEAD/JDK_RBT/bin/warmUp/InvertBinaryTree.class -------------------------------------------------------------------------------- /JDK_RBT/bin/rbt/ReflectUtilForTreeMap.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosoraYintai/TreeMapSourceAnalysis/HEAD/JDK_RBT/bin/rbt/ReflectUtilForTreeMap.class -------------------------------------------------------------------------------- /JDK_RBT/bin/bstAVL/InorderSuccessorInBST.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosoraYintai/TreeMapSourceAnalysis/HEAD/JDK_RBT/bin/bstAVL/InorderSuccessorInBST.class -------------------------------------------------------------------------------- /JDK_RBT/bin/bstAVL/ConvertSortedArrayToBinarySearchTree.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosoraYintai/TreeMapSourceAnalysis/HEAD/JDK_RBT/bin/bstAVL/ConvertSortedArrayToBinarySearchTree.class -------------------------------------------------------------------------------- /JDK_RBT/src/bstAVL/Person.java: -------------------------------------------------------------------------------- 1 | package bstAVL; 2 | 3 | public class Person { 4 | public int id; 5 | public String name; 6 | public Person(int id, String name) { 7 | super(); 8 | this.id = id; 9 | this.name = name; 10 | } 11 | @Override 12 | public String toString() { 13 | return "Person [id=" + id + ", name=" + name + "]"; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /JDK_RBT/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /JDK_RBT/src/warmUp/TestLinkedList.java: -------------------------------------------------------------------------------- 1 | package warmUp; 2 | 3 | import java.util.Arrays; 4 | import java.util.LinkedList; 5 | 6 | import org.junit.Test; 7 | 8 | public class TestLinkedList { 9 | @Test 10 | public void testQuery(){ 11 | LinkedList list=new LinkedList(Arrays.asList(0,1,2,3,4,5,6,7,8,9,10,11)); 12 | System.out.println(list.get(3)); 13 | System.out.println(list.get(9)); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /JDK_RBT/src/warmUp/TreeNode.java: -------------------------------------------------------------------------------- 1 | package warmUp; 2 | 3 | public class TreeNode { 4 | public int val; 5 | public TreeNode left; 6 | public TreeNode right; 7 | public TreeNode(int x) { 8 | val = x; 9 | } 10 | public TreeNode(int val, TreeNode left, TreeNode right) { 11 | super(); 12 | this.val = val; 13 | this.left = left; 14 | this.right = right; 15 | } 16 | public TreeNode() { 17 | super(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /JDK_RBT/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | #Mon Apr 30 19:44:11 CST 2018 2 | eclipse.preferences.version=1 3 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 4 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 5 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 6 | org.eclipse.jdt.core.compiler.compliance=1.6 7 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 8 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 9 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 10 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 11 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 12 | org.eclipse.jdt.core.compiler.source=1.6 13 | -------------------------------------------------------------------------------- /JDK_RBT/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | JDK_RBT 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | 19 | src/warmUp/AVLEntry.class 20 | 1 21 | D:/Program Files/Genuitec/Workspaces/MyEclipse 10/JDK_RBT/bin/bstAVL/AVLEntry.class 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /JDK_RBT/src/bstAVL/BSTIterator.java: -------------------------------------------------------------------------------- 1 | package bstAVL; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Iterator; 5 | 6 | import warmUp.TreeNode; 7 | 8 | public class BSTIterator { 9 | private Iterator itr; 10 | public BSTIterator(TreeNode root) { 11 | ArrayList list=new ArrayList(); 12 | inOrder(root, list); 13 | itr=list.iterator(); 14 | } 15 | private void inOrder(TreeNode p,ArrayList list){ 16 | if(p!=null){ 17 | inOrder(p.left, list); 18 | list.add(p.val); 19 | inOrder(p.right, list); 20 | } 21 | } 22 | /** @return whether we have a next smallest number */ 23 | public boolean hasNext() { 24 | return itr.hasNext(); 25 | } 26 | 27 | /** @return the next smallest number */ 28 | public int next() { 29 | return itr.next(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /JDK_RBT/src/bstAVL/AVLIterator.java: -------------------------------------------------------------------------------- 1 | package bstAVL; 2 | 3 | import java.util.ConcurrentModificationException; 4 | import java.util.Iterator; 5 | import java.util.Stack; 6 | 7 | public class AVLIterator implements Iterator>{ 8 | 9 | private Stack> stack; 10 | 11 | public AVLIterator(AVLEntry root) { 12 | super(); 13 | stack=new Stack>(); 14 | addLeftPath(root); 15 | } 16 | 17 | private void addLeftPath(AVLEntry p){ 18 | while(p!=null){ 19 | stack.push(p); 20 | p=p.left; 21 | } 22 | } 23 | @Override 24 | public boolean hasNext() { 25 | return stack.isEmpty()?false:true; 26 | } 27 | 28 | @Override 29 | public AVLEntry next() { 30 | AVLEntry p=stack.pop(); 31 | addLeftPath(p.right); 32 | return p; 33 | } 34 | 35 | @Override 36 | public void remove() { 37 | throw new ConcurrentModificationException("Can not remove!"); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /JDK_RBT/src/bstAVL/AVLEntry.java: -------------------------------------------------------------------------------- 1 | package bstAVL; 2 | 3 | import java.util.Map; 4 | 5 | public class AVLEntry implements Map.Entry{ 6 | public K key; 7 | public V value; 8 | public AVLEntry left; 9 | public AVLEntry right; 10 | public int height=1; 11 | @Override 12 | public K getKey() { 13 | return key; 14 | } 15 | 16 | @Override 17 | public V getValue() { 18 | return value; 19 | } 20 | 21 | @Override 22 | public V setValue(V value) { 23 | this.value=value; 24 | return value; 25 | } 26 | 27 | public AVLEntry(K key, V value) { 28 | super(); 29 | this.key = key; 30 | this.value = value; 31 | } 32 | 33 | public AVLEntry(K key) { 34 | super(); 35 | this.key = key; 36 | } 37 | 38 | public AVLEntry(K key, V value, AVLEntry left, AVLEntry right) { 39 | super(); 40 | this.key = key; 41 | this.value = value; 42 | this.left = left; 43 | this.right = right; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | return "AVLEntry [key=" + key + ", value=" + value + ", height=" 49 | + height + "]"; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /JDK_RBT/src/warmUp/InvertBinaryTree.java: -------------------------------------------------------------------------------- 1 | package warmUp; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | 6 | public class InvertBinaryTree { 7 | public TreeNode invertTree(TreeNode root) { 8 | if(root!=null){ 9 | TreeNode t=root.left; 10 | root.left=root.right; 11 | root.right=t; 12 | invertTree(root.left); 13 | invertTree(root.right); 14 | return root; 15 | }else{ 16 | return null; 17 | } 18 | } 19 | public TreeNode invertTree_bfs(TreeNode root) { 20 | if(root==null){ 21 | return null; 22 | }else{ 23 | Queue queue=new LinkedList(); 24 | queue.offer(root); 25 | while(!queue.isEmpty()){ 26 | TreeNode p=queue.poll(); 27 | TreeNode t=p.left; 28 | p.left=p.right; 29 | p.right=t; 30 | if(p.left!=null){ 31 | queue.offer(p.left); 32 | } 33 | if(p.right!=null){ 34 | queue.offer(p.right); 35 | } 36 | 37 | } 38 | return root; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /JDK_RBT/src/bstAVL/InorderSuccessorInBST.java: -------------------------------------------------------------------------------- 1 | package bstAVL; 2 | 3 | import warmUp.TreeNode; 4 | 5 | public class InorderSuccessorInBST { 6 | public TreeNode inorderSuccessor(TreeNode root, TreeNode p) { 7 | if(p==null){ 8 | return null; 9 | } 10 | if(getLastEntry(root)==p){ 11 | return null; 12 | } 13 | if(p.right!=null){ 14 | return getFirstEntry(p.right); 15 | } 16 | TreeNode parent=root; 17 | TreeNode temp=root; 18 | while(parent!=null){ 19 | if(parent==p){ 20 | break; 21 | }else if(p.val map1=new AVLMap(); 16 | private static TreeMap map2=new TreeMap(); 17 | @Test 18 | public void _1_TestAVLInsert(){ 19 | for(int i=0;i>>1;i++){ 44 | map1.remove(random.nextInt(Max)); 45 | } 46 | } 47 | @Test 48 | public void _6_TestRBTRemove(){ 49 | for(int i=0;i>>1;i++){ 50 | map2.remove(random.nextInt(Max)); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /JDK_RBT/src/bstAVL/TestBSTVSTreeMap.java: -------------------------------------------------------------------------------- 1 | package bstAVL; 2 | 3 | import java.util.Random; 4 | import java.util.TreeMap; 5 | 6 | import org.junit.Test; 7 | 8 | public class TestBSTVSTreeMap { 9 | public static final int MAX=65535; 10 | private Random random=new Random(); 11 | @Test 12 | public void testBSTRandom(){ 13 | AVLMap map=new AVLMap(); 14 | for(int i=0;i map=new TreeMap(); 25 | for(int i=0;i map=new AVLMap(); 35 | for(int i=0;i map=new TreeMap(); 46 | for(int i=0;i entryClass; 11 | public static Field leftField; 12 | public static Field rightField; 13 | public static Class treeMapClass; 14 | public static Field rootField; 15 | public static Field colorFiled; 16 | static{ 17 | try { 18 | entryClass=Class.forName("java.util.TreeMap$Entry"); 19 | leftField=entryClass.getDeclaredField("left"); 20 | leftField.setAccessible(true); 21 | rightField=entryClass.getDeclaredField("right"); 22 | rightField.setAccessible(true); 23 | treeMapClass=TreeMap.class; 24 | rootField=treeMapClass.getDeclaredField("root"); 25 | rootField.setAccessible(true); 26 | colorFiled=entryClass.getDeclaredField("color"); 27 | colorFiled.setAccessible(true); 28 | } catch (SecurityException e) { 29 | e.printStackTrace(); 30 | } catch (ClassNotFoundException e) { 31 | e.printStackTrace(); 32 | } catch (NoSuchFieldException e) { 33 | e.printStackTrace(); 34 | } 35 | } 36 | private static void printTreeNode(Map.Entry p) throws Exception{ 37 | boolean color=(Boolean) colorFiled.getBoolean(p); 38 | String colorStr=""; 39 | if(color){ 40 | colorStr="BLACK"; 41 | }else{ 42 | colorStr="RED"; 43 | } 44 | System.out.print(p.getKey()+"-"+colorStr+"-"+p.getValue()+" "); 45 | } 46 | /** 47 | * 层序输出JDK的红黑树 48 | */ 49 | @SuppressWarnings("unchecked") 50 | public static void levelOrderPrintTree(TreeMap map) throws Exception{ 51 | Map.Entry root=(Map.Entry) rootField.get(map); 52 | if(root==null){ 53 | return; 54 | } 55 | Queue> queue=new LinkedList>(); 56 | queue.offer(root); 57 | int preCount=1; 58 | int pCount=0; 59 | while(!queue.isEmpty()){ 60 | Map.Entry p=queue.poll(); 61 | preCount--; 62 | printTreeNode(p); 63 | if((Map.Entry)leftField.get(p)!=null){ 64 | queue.offer((Map.Entry)leftField.get(p)); 65 | pCount++; 66 | } 67 | if((Map.Entry)rightField.get(p)!=null){ 68 | queue.offer((Map.Entry)rightField.get(p)); 69 | pCount++; 70 | } 71 | if(preCount==0){ 72 | preCount=pCount; 73 | pCount=0; 74 | System.out.println(); 75 | } 76 | } 77 | System.out.println("------------------------"); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /JDK_RBT/src/bstAVL/ConvertSortedArrayToBinarySearchTree.java: -------------------------------------------------------------------------------- 1 | package bstAVL; 2 | 3 | import java.util.HashMap; 4 | import java.util.LinkedList; 5 | 6 | import warmUp.TreeNode; 7 | class LeetCodeAVL { 8 | 9 | private int size; 10 | public TreeNode root; 11 | private LinkedList stack = new LinkedList(); 12 | 13 | public int size() { 14 | return size; 15 | } 16 | public boolean isEmpty() { 17 | return size == 0 ? true : false; 18 | } 19 | 20 | public void put(int key) { 21 | if (root == null) { 22 | root = new TreeNode(key); 23 | stack.push(root); 24 | size++; 25 | } else { 26 | TreeNode p = root; 27 | while (p != null) { 28 | stack.push(p); 29 | int compareResult = key - p.val; 30 | if (compareResult == 0) { 31 | break; 32 | } else if (compareResult < 0) { 33 | if (p.left == null) { 34 | p.left = new TreeNode(key); 35 | size++; 36 | stack.push(p.left); 37 | break; 38 | } else { 39 | p = p.left; 40 | } 41 | } else { 42 | if (p.right == null) { 43 | p.right = new TreeNode(key); 44 | size++; 45 | stack.push(p.right); 46 | break; 47 | } else { 48 | p = p.right; 49 | } 50 | } 51 | } 52 | } 53 | fixAfterInsertion(key); 54 | } 55 | private HashMap heightMap = new HashMap(); 56 | public int getHeight(TreeNode p) { 57 | return heightMap.containsKey(p) ? heightMap.get(p) : 0; 58 | } 59 | private TreeNode rotateRight(TreeNode p) { 60 | TreeNode left = p.left; 61 | p.left = left.right; 62 | left.right = p; 63 | heightMap.put(p, Math.max(getHeight(p.left), getHeight(p.right)) + 1); 64 | heightMap.put(left, 65 | Math.max(getHeight(left.left), heightMap.get(p)) + 1); 66 | return left; 67 | } 68 | private TreeNode rotateLeft(TreeNode p) { 69 | TreeNode right = p.right; 70 | p.right = right.left; 71 | right.left = p; 72 | heightMap.put(p, Math.max(getHeight(p.left), getHeight(p.right)) + 1); 73 | heightMap 74 | .put(right, Math.max(getHeight(p), getHeight(right.right)) + 1); 75 | return right; 76 | } 77 | private TreeNode firstLeftThenRight(TreeNode p) { 78 | p.left = rotateLeft(p.left); 79 | p = rotateRight(p); 80 | return p; 81 | } 82 | private TreeNode firstRightThenLeft(TreeNode p) { 83 | p.right = rotateRight(p.right); 84 | p = rotateLeft(p); 85 | return p; 86 | } 87 | private void fixAfterInsertion(int key) { 88 | TreeNode p = root; 89 | while (!stack.isEmpty()) { 90 | p = stack.pop(); 91 | int newHeight = Math.max(getHeight(p.left), getHeight(p.right)) + 1; 92 | if (heightMap.containsKey(p) && getHeight(p) > 1 93 | && newHeight == getHeight(p)) { 94 | stack.clear(); 95 | return; 96 | } 97 | heightMap.put(p, newHeight); 98 | int d = getHeight(p.left) - getHeight(p.right); 99 | if (Math.abs(d) <= 1) { 100 | continue; 101 | } else { 102 | if (d == 2) { 103 | if (key - p.left.val < 0) { 104 | p = rotateRight(p); 105 | } else { 106 | p = firstLeftThenRight(p); 107 | } 108 | } else { 109 | if (key - p.right.val > 0) { 110 | p = rotateLeft(p); 111 | } else { 112 | p = firstRightThenLeft(p); 113 | } 114 | } 115 | if (!stack.isEmpty()) { 116 | if (key - stack.peek().val < 0) { 117 | stack.peek().left = p; 118 | } else { 119 | stack.peek().right = p; 120 | } 121 | } 122 | } 123 | } 124 | root = p; 125 | } 126 | } 127 | public class ConvertSortedArrayToBinarySearchTree { 128 | public TreeNode sortedArrayToBST_UsingAVL(int[] nums) { 129 | if (nums == null || nums.length == 0) { 130 | return null; 131 | } 132 | LeetCodeAVL avl = new LeetCodeAVL(); 133 | for (int key : nums) { 134 | avl.put(key); 135 | } 136 | return avl.root; 137 | } 138 | public TreeNode sortedArrayToBST(int[] nums) { 139 | if (nums == null || nums.length == 0) { 140 | return null; 141 | } 142 | return buildFromSorted(0, nums.length-1, nums); 143 | } 144 | private TreeNode buildFromSorted(int lo, int hi,int[] nums) { 145 | if (hi < lo) 146 | return null; 147 | 148 | int mid = (lo + hi) / 2; 149 | 150 | TreeNode left = null; 151 | if (lo < mid) 152 | left = buildFromSorted(lo, mid - 1, nums); 153 | TreeNode middle = new TreeNode(nums[mid]); 154 | if (left != null) { 155 | middle.left = left; 156 | } 157 | if (mid < hi) { 158 | TreeNode right = buildFromSorted(mid + 1, hi,nums); 159 | middle.right = right; 160 | } 161 | return middle; 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /JDK_RBT/src/rbt/TestRBT.java: -------------------------------------------------------------------------------- 1 | package rbt; 2 | 3 | import java.util.TreeMap; 4 | 5 | import org.junit.Test; 6 | 7 | public class TestRBT { 8 | @Test 9 | public void testPrint() throws Exception{ 10 | TreeMap map=new TreeMap(); 11 | map.put(2, 2); 12 | map.put(4, 4); 13 | map.put(1, 1); 14 | map.put(6, 6); 15 | map.put(5, 5); 16 | map.put(3, 3); 17 | ReflectUtilForTreeMap.levelOrderPrintTree(map); 18 | } 19 | @Test 20 | public void testInsert() throws Exception{ 21 | TreeMap map=new TreeMap(); 22 | // 依次插入:12,1,9,2,0,11,7,19,4,15,18,5 23 | // root,blackHeight=1; 24 | map.put(12, 12); 25 | ReflectUtilForTreeMap.levelOrderPrintTree(map); 26 | // bpOver 27 | map.put(1, 1); 28 | ReflectUtilForTreeMap.levelOrderPrintTree(map); 29 | // leftCase2 --> leftCase3 30 | map.put(9, 9); 31 | ReflectUtilForTreeMap.levelOrderPrintTree(map); 32 | // leftCase1 --> rootOver,blackHeight=2; 33 | map.put(2, 2); 34 | ReflectUtilForTreeMap.levelOrderPrintTree(map); 35 | // bpOver 36 | map.put(0, 0); 37 | ReflectUtilForTreeMap.levelOrderPrintTree(map); 38 | // bpOver 39 | map.put(11, 11); 40 | ReflectUtilForTreeMap.levelOrderPrintTree(map); 41 | // rightCase1 --> bpOver 42 | map.put(7, 7); 43 | ReflectUtilForTreeMap.levelOrderPrintTree(map); 44 | // bpOver 45 | map.put(19, 19); 46 | ReflectUtilForTreeMap.levelOrderPrintTree(map); 47 | // rightCase2 --> rightCase3 48 | Integer key4=4; 49 | map.put(key4, key4); 50 | ReflectUtilForTreeMap.levelOrderPrintTree(map); 51 | // rightCase1 --> bpOver 52 | map.put(15, 15); 53 | ReflectUtilForTreeMap.levelOrderPrintTree(map); 54 | // leftCase2 --> leftCase3 55 | map.put(18, 18); 56 | ReflectUtilForTreeMap.levelOrderPrintTree(map); 57 | // rightCase1 --> leftCase1 --> rootOver,blackHeight=3 58 | // case1可以执行多次 59 | Integer key5=5; 60 | map.put(key5, key5); 61 | ReflectUtilForTreeMap.levelOrderPrintTree(map); 62 | // 插入余下的数字 63 | int[] others={14,13,10,16,6,3,8,17}; 64 | for(int key:others){ 65 | map.put(key, key); 66 | } 67 | ReflectUtilForTreeMap.levelOrderPrintTree(map); 68 | } 69 | @Test 70 | public void testRemove(){ 71 | TreeMap map=new TreeMap(); 72 | int[] array={12,1,9,2,0,11,7,19,4,15,18,5,14,13,10,16,6,3,8,17}; 73 | for(int key:array){ 74 | map.put(key, key); 75 | } 76 | // successor --> fix(p) | rightCase4-2 | p=null 77 | Integer key12=12; 78 | map.remove(key12); 79 | 80 | // successor --> replacement --> p=null --> fix(replacement) | redOver 81 | Integer key1=1; 82 | map.remove(key1); 83 | 84 | // successor --> fix(p) | leftCase2-2 --> redOver | p=null 85 | Integer key9=9; 86 | map.remove(key9); 87 | 88 | // successor --> fix(p) | rightCase2-2 --> redOver | p=null 89 | Integer key2=2; 90 | map.remove(key2); 91 | 92 | // p=null 93 | Integer key0=0; 94 | map.remove(key0); 95 | 96 | // replacement --> p=null --> fix(replacement) | redOver 97 | Integer key11=11; 98 | map.remove(key11); 99 | 100 | // replacement --> p=null --> fix(replacement) | redOver 101 | Integer key7=7; 102 | map.remove(key7); 103 | 104 | // fix(p) | rightCase4-1 | p=null 105 | Integer key19=19; 106 | map.remove(key19); 107 | 108 | // successor --> fix(p) | leftCase2-2 --> redOver | p=null 109 | Integer key4=4; 110 | map.remove(key4); 111 | 112 | // fix(p) | leftCase3 --> leftCase4-2 | p=null 113 | System.out.println("fix(p) | leftCase3 --> leftCase4-2 | p=null"); 114 | Integer key15=15; 115 | map.remove(key15); 116 | 117 | // fix(p) | rightCase2-2 --> redOver | p=null 118 | Integer key18=18; 119 | map.remove(key18); 120 | 121 | // successor --> replacement --> p=null --> fix(replacement) | redOver 122 | Integer key5=5; 123 | map.remove(key5); 124 | 125 | // successor --> p=null 126 | System.out.println("successor --> p=null"); 127 | Integer key14=14; 128 | map.remove(key14); 129 | 130 | // fix(p) | leftCase2-1 --> rightCase2-1 --> rootOver | p=null,blackHeight=2 131 | System.out.println("fix(p) | leftCase2-1 --> rightCase2-1 --> rootOver | p=null,blackHeight=2"); 132 | Integer key13=13; 133 | map.remove(key13); 134 | 135 | // successor --> replacement --> p=null --> fix(replacement) | redOver 136 | Integer key10=10; 137 | map.remove(key10); 138 | 139 | // successor --> fix(p) | rightCase1 --> rightCase2-2 --> redOver | p=null 140 | Integer key16=16; 141 | map.remove(key16); 142 | 143 | // successor --> p=null 144 | Integer key6=6; 145 | map.remove(key6); 146 | 147 | // fix(p) | leftCase2-1 --> rootOver | p=null,blackHeight=1 148 | Integer key3=3; 149 | map.remove(key3); 150 | 151 | // replacement --> p=null --> fix(replacement) | rootOver&redOver 152 | Integer key8=8; 153 | map.remove(key8); 154 | 155 | // root=null,blackHeight=0 156 | Integer key17=17; 157 | map.remove(key17); 158 | 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /JDK_RBT/src/bstAVL/TestBST.java: -------------------------------------------------------------------------------- 1 | package bstAVL; 2 | 3 | import java.util.Comparator; 4 | import java.util.Iterator; 5 | import java.util.Map; 6 | import java.util.Random; 7 | import java.util.TreeMap; 8 | 9 | import org.junit.Assert; 10 | import org.junit.Test; 11 | 12 | public class TestBST { 13 | private Random random=new Random(); 14 | private final int MAX1=16; 15 | @Test 16 | public void testPutAndItr(){ 17 | AVLMap map=new AVLMap(); 18 | for(int i=0;i> it=map.iterator(); 22 | while(it.hasNext()){ 23 | System.out.print(it.next().key+" "); 24 | } 25 | System.out.println(); 26 | } 27 | private final int MAX2=65535; 28 | @Test 29 | public void testPutAndItrWithJDK(){ 30 | AVLMap map1=new AVLMap(); 31 | TreeMap map2=new TreeMap(); 32 | for(int i=0;i> it1=map1.iterator(); 41 | Iterator> it2=map2.entrySet().iterator(); 42 | while(it1.hasNext()&&it2.hasNext()){ 43 | Assert.assertTrue(it1.next().getKey().equals(it2.next().getKey())); 44 | } 45 | Assert.assertTrue(!it1.hasNext()&&!it2.hasNext()); 46 | } 47 | @Test 48 | public void testQuery(){ 49 | AVLMap map=new AVLMap(); 50 | map.put(4, "a"); 51 | map.put(2, "b"); 52 | map.put(6, "c"); 53 | map.put(2, "d"); 54 | map.put(1, "a"); 55 | map.put(3, "d"); 56 | map.put(5, "e"); 57 | map.put(1, "f"); 58 | Assert.assertTrue(map.get(4).equals("a")); 59 | Assert.assertTrue(map.get(1).equals("f")); 60 | Assert.assertTrue(map.get(7)==null); 61 | Assert.assertTrue(map.containsKey(6)); 62 | Assert.assertTrue(!map.containsKey(-1)); 63 | Assert.assertTrue(map.containsValue("d")); 64 | Assert.assertTrue(!map.containsValue("xxxx")); 65 | } 66 | @Test 67 | public void testQUeryWithJDK(){ 68 | AVLMap map1=new AVLMap(); 69 | TreeMap map2=new TreeMap(); 70 | for(int i=0;i map=new AVLMap(); 93 | int[] array={5,2,6,1,4,7,3}; 94 | for(int key:array){ 95 | map.put(key, key+""); 96 | } 97 | System.out.println(map.remove(1)); 98 | map.levelOrder(); 99 | Iterator> it=map.iterator(); 100 | while(it.hasNext()){ 101 | System.out.print(it.next().key+" "); 102 | } 103 | System.out.println(); 104 | } 105 | @Test 106 | public void testRemoveCase2(){ 107 | AVLMap map=new AVLMap(); 108 | int[] array={5,2,6,1,4,7,3}; 109 | for(int key:array){ 110 | map.put(key, key+""); 111 | } 112 | System.out.println(map.remove(4)); 113 | map.levelOrder(); 114 | Iterator> it=map.iterator(); 115 | while(it.hasNext()){ 116 | System.out.print(it.next().key+" "); 117 | } 118 | System.out.println(); 119 | } 120 | @Test 121 | public void testRemoveCase3(){ 122 | AVLMap map=new AVLMap(); 123 | int[] array={6,2,7,1,4,8,3,5}; 124 | for(int key:array){ 125 | map.put(key, key+""); 126 | } 127 | System.out.println(map.remove(2)); 128 | map.levelOrder(); 129 | Iterator> it=map.iterator(); 130 | while(it.hasNext()){ 131 | System.out.print(it.next().key+" "); 132 | } 133 | System.out.println(); 134 | } 135 | @Test 136 | public void testRemoveWithJDK(){ 137 | AVLMap map1=new AVLMap(); 138 | TreeMap map2=new TreeMap(); 139 | for(int i=0;i>>1;i++){ 147 | int key=random.nextInt(MAX2); 148 | if(map1.containsKey(key)){ 149 | Assert.assertTrue(map1.remove(key).equals(map2.remove(key))); 150 | }else{ 151 | Assert.assertTrue(map1.remove(key)==null&&map2.remove(key)==null); 152 | } 153 | } 154 | System.out.println(map1.size()); 155 | Assert.assertTrue(map1.size()==map2.size()); 156 | Iterator> it1=map1.iterator(); 157 | Iterator> it2=map2.entrySet().iterator(); 158 | while(it1.hasNext()&&it2.hasNext()){ 159 | Assert.assertTrue(it1.next().getKey().equals(it2.next().getKey())); 160 | } 161 | Assert.assertTrue(!it1.hasNext()&&!it2.hasNext()); 162 | } 163 | @Test 164 | public void testPerson(){ 165 | AVLMap map=new AVLMap(new Comparator() { 166 | @Override 167 | public int compare(Person o1, Person o2) { 168 | return o2.id-o1.id; 169 | } 170 | }); 171 | for(int i=0;i> itr=map.iterator(); 175 | while(itr.hasNext()){ 176 | System.out.println(itr.next().getKey()); 177 | } 178 | } 179 | @Test 180 | public void testAVLDelete(){ 181 | AVLMap map1=new AVLMap(); 182 | TreeMap map2=new TreeMap(); 183 | for(int i=0;i>1;i++){ 190 | int key=random.nextInt(MAX2); 191 | map1.remove(key); 192 | map2.remove(key); 193 | } 194 | map1.checkBalance(); 195 | Assert.assertTrue(map1.size()==map2.size()); 196 | Iterator> it1=map1.iterator(); 197 | Iterator> it2=map2.entrySet().iterator(); 198 | while(it1.hasNext()&&it2.hasNext()){ 199 | Assert.assertTrue(it1.next().getKey().equals(it2.next().getKey())); 200 | } 201 | Assert.assertTrue(!it1.hasNext()&&!it2.hasNext()); 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /JDK_RBT/src/bstAVL/AVLMap.java: -------------------------------------------------------------------------------- 1 | package bstAVL; 2 | 3 | import java.util.Comparator; 4 | import java.util.Iterator; 5 | import java.util.LinkedList; 6 | import java.util.Queue; 7 | 8 | import org.junit.Assert; 9 | 10 | public class AVLMap implements Iterable>{ 11 | private int size; 12 | private AVLEntry root; 13 | private Comparator comp; 14 | private LinkedList> stack=new LinkedList>(); 15 | @SuppressWarnings("unchecked") 16 | private int compare(K a, K b) { 17 | if (comp != null) { 18 | return comp.compare(a, b); 19 | } else { 20 | Comparable c = (Comparable) a; 21 | return c.compareTo(b); 22 | } 23 | } 24 | public AVLMap(Comparator comp) { 25 | super(); 26 | this.comp = comp; 27 | } 28 | public AVLMap() { 29 | super(); 30 | } 31 | public int size() { 32 | return size; 33 | } 34 | public boolean isEmpty() { 35 | return size == 0 ? true : false; 36 | } 37 | 38 | public V put(K key,V value){ 39 | if(root==null){ 40 | root=new AVLEntry(key, value); 41 | stack.push(root); 42 | size++; 43 | }else{ 44 | AVLEntry p=root; 45 | while(p!=null){ 46 | stack.push(p); 47 | int compareResult=compare(key, p.key); 48 | if(compareResult==0){ 49 | p.setValue(value); 50 | break; 51 | }else if(compareResult<0){ 52 | if(p.left==null){ 53 | p.left=new AVLEntry(key, value); 54 | size++; 55 | stack.push(p.left); 56 | break; 57 | }else{ 58 | p=p.left; 59 | } 60 | }else{ 61 | if(p.right==null){ 62 | p.right=new AVLEntry(key, value); 63 | size++; 64 | stack.push(p.right); 65 | break; 66 | }else{ 67 | p=p.right; 68 | } 69 | } 70 | } 71 | } 72 | fixAfterInsertion(key); 73 | return value; 74 | } 75 | @Override 76 | public Iterator> iterator() { 77 | return new AVLIterator(root); 78 | } 79 | 80 | private AVLEntry getEntry(K key){ 81 | AVLEntry p=root; 82 | while(p!=null){ 83 | int compareResult=compare(key, p.key); 84 | if(compareResult==0){ 85 | return p; 86 | }else if(compareResult<0){ 87 | p=p.left; 88 | }else{ 89 | p=p.right; 90 | } 91 | } 92 | return null; 93 | } 94 | public boolean containsKey(K key){ 95 | AVLEntry p=getEntry(key); 96 | return p!=null; 97 | } 98 | public V get(K key){ 99 | AVLEntry p=getEntry(key); 100 | return p!=null?p.getValue():null; 101 | } 102 | public boolean containsValue(V value){ 103 | Iterator> itr=this.iterator(); 104 | while(itr.hasNext()){ 105 | if(itr.next().getValue().equals(value)){ 106 | return true; 107 | } 108 | } 109 | return false; 110 | } 111 | public AVLEntry getFirstEntry(AVLEntry p){ 112 | if(p==null){ 113 | return null; 114 | } 115 | while(p.left!=null){ 116 | p=p.left; 117 | } 118 | return p; 119 | } 120 | public AVLEntry getLastEntry(AVLEntry p){ 121 | if(p==null){ 122 | return null; 123 | } 124 | while(p.right!=null){ 125 | p=p.right; 126 | } 127 | return p; 128 | } 129 | private AVLEntry deleteEntry(AVLEntry p,K key){ 130 | if(p==null){ 131 | return null; 132 | }else{ 133 | int compareResult=compare(key, p.key); 134 | if(compareResult==0){ 135 | if(p.left==null&&p.right==null){ 136 | p=null; 137 | }else if(p.left!=null&&p.right==null){ 138 | p=p.left; 139 | }else if(p.left==null&&p.right!=null){ 140 | p=p.right; 141 | }else{ 142 | if((size&1)==0){ 143 | AVLEntry rightMin=getFirstEntry(p.right); 144 | p.key=rightMin.key; 145 | p.value=rightMin.value; 146 | AVLEntry newRight=deleteEntry(p.right, p.key); 147 | p.right=newRight; 148 | }else{ 149 | AVLEntry leftMax=getLastEntry(p.left); 150 | p.key=leftMax.key; 151 | p.value=leftMax.value; 152 | AVLEntry newLeft=deleteEntry(p.left, p.key); 153 | p.left=newLeft; 154 | } 155 | } 156 | }else if(compareResult<0){ 157 | AVLEntry newLeft=deleteEntry(p.left, key); 158 | p.left=newLeft; 159 | }else{ 160 | AVLEntry newRight=deleteEntry(p.right, key); 161 | p.right=newRight; 162 | } 163 | p=fixAfterDeletion(p); 164 | return p; 165 | } 166 | } 167 | public int getHeight(AVLEntry p){ 168 | return p==null?0:p.height; 169 | } 170 | private AVLEntry rotateRight(AVLEntry p){ 171 | AVLEntry left=p.left; 172 | p.left=left.right; 173 | left.right=p; 174 | p.height=Math.max(getHeight(p.left), getHeight(p.right))+1; 175 | left.height=Math.max(getHeight(left.left), p.height)+1; 176 | return left; 177 | } 178 | private AVLEntry rotateLeft(AVLEntry p){ 179 | AVLEntry right=p.right; 180 | p.right=right.left; 181 | right.left=p; 182 | p.height=Math.max(getHeight(p.left), getHeight(p.right))+1; 183 | right.height=Math.max(p.height, getHeight(right.right))+1; 184 | return right; 185 | } 186 | private AVLEntry firstLeftThenRight(AVLEntry p){ 187 | p.left=rotateLeft(p.left); 188 | p=rotateRight(p); 189 | return p; 190 | } 191 | private AVLEntry firstRightThenLeft(AVLEntry p){ 192 | p.right=rotateRight(p.right); 193 | p=rotateLeft(p); 194 | return p; 195 | } 196 | private void fixAfterInsertion(K key){ 197 | AVLEntry p=root; 198 | while(!stack.isEmpty()){ 199 | p=stack.pop(); 200 | int newHeight=Math.max(getHeight(p.left), getHeight(p.right))+1; 201 | if(p.height>1&&newHeight==p.height){ 202 | stack.clear(); 203 | return; 204 | } 205 | p.height=newHeight; 206 | int d=getHeight(p.left)-getHeight(p.right); 207 | if(Math.abs(d)<=1){ 208 | continue; 209 | }else{ 210 | if(d==2){ 211 | if(compare(key, p.left.key)<0){ 212 | p=rotateRight(p); 213 | }else{ 214 | p=firstLeftThenRight(p); 215 | } 216 | }else{ 217 | if(compare(key, p.right.key)>0){ 218 | p=rotateLeft(p); 219 | }else{ 220 | p=firstRightThenLeft(p); 221 | } 222 | } 223 | if(!stack.isEmpty()){ 224 | if(compare(key, stack.peek().key)<0){ 225 | stack.peek().left=p; 226 | }else{ 227 | stack.peek().right=p; 228 | } 229 | } 230 | } 231 | } 232 | root=p; 233 | } 234 | public void checkBalance(){ 235 | postOrderCheckBalance(root); 236 | } 237 | private void postOrderCheckBalance(AVLEntry p){ 238 | if(p!=null){ 239 | postOrderCheckBalance(p.left); 240 | postOrderCheckBalance(p.right); 241 | Assert.assertTrue(Math.abs(getHeight(p.left)-getHeight(p.right))<=1); 242 | } 243 | } 244 | public V remove(K key){ 245 | AVLEntry entry=getEntry(key); 246 | if(entry==null){ 247 | return null; 248 | } 249 | V oldValue=entry.getValue(); 250 | root=deleteEntry(root, key); 251 | size--; 252 | return oldValue; 253 | } 254 | public void levelOrder(){ 255 | Queue> queue=new LinkedList>(); 256 | queue.offer(root); 257 | int preCount=1; 258 | int pCount=0; 259 | while(!queue.isEmpty()){ 260 | preCount--; 261 | AVLEntry p=queue.poll(); 262 | System.out.print(p+" "); 263 | if(p.left!=null){ 264 | queue.offer(p.left); 265 | pCount++; 266 | } 267 | if(p.right!=null){ 268 | queue.offer(p.right); 269 | pCount++; 270 | } 271 | if(preCount==0){ 272 | preCount=pCount; 273 | pCount=0; 274 | System.out.println(); 275 | } 276 | } 277 | } 278 | public AVLEntry fixAfterDeletion(AVLEntry p){ 279 | if(p==null){ 280 | return null; 281 | }else{ 282 | p.height=Math.max(getHeight(p.left), getHeight(p.right))+1; 283 | int d=getHeight(p.left)-getHeight(p.right); 284 | if(d==2){ 285 | if(getHeight(p.left.left)-getHeight(p.left.right)>=0){ 286 | p=rotateRight(p); 287 | }else{ 288 | p=firstLeftThenRight(p); 289 | } 290 | }else if(d==-2){ 291 | if(getHeight(p.right.right)-getHeight(p.right.left)>=0){ 292 | p=rotateLeft(p); 293 | }else{ 294 | p=firstRightThenLeft(p); 295 | } 296 | } 297 | return p; 298 | } 299 | } 300 | } 301 | --------------------------------------------------------------------------------