TreeMap是基于红黑树结构实现的一种Map,要分析TreeMap的实现首先就要对红黑树有所了解。
     要了解什么是红黑树,就要了解它的存在主要是为了解决什么问题,对比其他数据结构比如数组,链表,Hash表等树这种结构又有什么优点。
 
1.二叉查询树、红黑树介绍
    
  以下为个人理解,有误请拍砖。。。
 
     下面我尽可能用通俗易懂的语言,简单总结一下数组,链表,Hash表以及树的优缺点。
     1.数组,优点:(1)随机访问效率高(根据下标查询),(2)搜索效率较高(可使用折半方法)。缺点:(1)内存连续且固定,存储效率低。(2)插入和删除效率低(可能会进行数组拷贝或扩容)。
     2.链表,优点:(1)不要求连续内存,内存利用率高,(2)插入和删除效率高(只需要改变指针指向)。缺点:(1)不支持随机访问,(2)搜索效率低(需要遍历)。
     3.Hash表:优点:(1)搜索效率高,(2)插入和删除效率较高,缺点:(1)内存利用率低(基于数组),(2)存在散列冲突。
     
     上面说的话比较啰嗦,再精炼一下:数组查询好、插入和删除差且浪费内存;链表插入和删除好、查询差;Hash表查询好、插入和删除也不错但是浪费内存。
     也就是说,查询好的插入和删除就差,插入和删除好的查询就差,好不容易有一个查询、插入和删除都不错的,但是却又浪费内存。哎,好苦恼啊,怎么办呢,愁死我啦。能不能做到查询、插入、删除效率都很高,又不浪费内存呢。答案当然是不能!哎,还是好愁人,烦死啦。但是可以做到查询、插入、删除效率比较高,又不浪费内存。哇塞,这是什么东东,这么牛掰,这就是二叉查询树(又叫二叉排序树,又叫二叉搜索树)。你说二叉树这么好,那有什么缺点吗,有!就是算法复杂。
 
     那么什么是二叉查找树呢,它又有哪些特点呢?(以下见于百度百科)
     (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
     (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
     (3)左、右子树也分别为二叉查找树;
     (4)没有键值相等的节点。
给jdk写注释系列之jdk1.6容器(7)-TreeMap源码解析
 
  按照二叉查找树存储的数据,对元素的搜索效率是非常高的,比如上图中如果要查找值为48的节点,只需要遍历4个节点就能完成。理论上,一颗平衡的二叉查找树的任意节点平均查找效率为树的高度h,即O(lgn)。但是如果二叉查找树的失去平衡(元素全在一侧),搜索效率就退化为O(n),因此二叉查找树的平衡是搜索效率的关键所在。而红黑树就是靠红黑规则来维持二叉查找树的平衡性
 
给jdk写注释系列之jdk1.6容器(7)-TreeMap源码解析
(一颗失去平衡的二叉树)
 
  简单用代码描述上面的二叉查找树,试试看:
  1 public class BinaryTree {
  2 
  3         // 二叉树的根节点
  4         public TreeNode rootNode ;
  5         // 记录搜索深度
  6         public int count;
  7 
  8         /**
  9         * 利用传入一个数组来建立二叉树
 10         */
 11         public BinaryTree(int[] data) {
 12                for (int i = 0; i < data. length; i++) {
 13                      addNodeToTree(data[i]);
 14               }
 15        }
 16 
 17         /**
 18         * 将指定的值加入到二叉树中适当的节点
 19         */
 20         private void addNodeToTree(int value) {
 21               TreeNode currentNode = rootNode;
 22                // 建立树根
 23                if (rootNode == null) {
 24                       rootNode = new TreeNode(value);
 25                       return;
 26               }
 27 
 28                // 建立二叉树
 29                while (true) {
 30                       // 新增的value比节点的value小,则在左子树
 31                       if (value < currentNode.value ) {
 32                             if (currentNode.leftNode == null) {
 33                                   currentNode. leftNode = new TreeNode(value);
 34                                    return;
 35                            } else {
 36                                   currentNode = currentNode. leftNode;
 37                            }
 38                      } else { // 新增的value比节点的value大,在右子树
 39                             if (currentNode.rightNode == null) {
 40                                   currentNode. rightNode = new TreeNode(value);
 41                                    return;
 42                            } else {
 43                                   currentNode = currentNode. rightNode;
 44                            }
 45                      }
 46               }
 47        }
 48 
 49         /**
 50         * 中序遍历(左子树 -树根- 右子树)
 51         */
 52         public void inOrder(TreeNode node) {
 53                if (node != null) {
 54                      inOrder(node. leftNode);
 55                      System. out.print("[" + node.value + "]");
 56                      inOrder(node. rightNode);
 57               }
 58        }
 59 
 60         /**
 61         * 前序遍历(树根 -左子树- 右子树)
 62         */
 63         public void preOrder(TreeNode node) {
 64                if (node != null) {
 65                      System. out.print("[" + node.value + "]");
 66                      preOrder(node. leftNode);
 67                      preOrder(node. rightNode);
 68               }
 69        }
 70 
 71         /**
 72         * 后序遍历(左子树 -右子树- 树根)
 73         */
 74         public void postOrder(TreeNode node) {
 75                if (node != null) {
 76                      postOrder(node. leftNode);
 77                      postOrder(node. rightNode);
 78                      System. out.print("[" + node.value + "]");
 79               }
 80        }
 81 
 82         /**
 83         * 从二叉树中查找指定value
 84         */
 85         public boolean findTree(TreeNode node, int value) {
 86                if (node == null) {
 87                      System. out.println("共搜索" + count + "次");
 88                       return false;
 89               } else if (node.value == value) {
 90                      System. out.println("共搜索" + count + "次");
 91                       return true;
 92               } else if (value < node.value) {
 93                       count++;
 94                       return findTree(node.leftNode , value);
 95               } else {
 96                       count++;
 97                       return findTree(node.rightNode , value);
 98               }
 99        }
100 
101         /**
102         * 利用中序遍历进行排序
103         */
104         public void sort() {
105                this.inOrder(rootNode );
106        }
107 
108         class TreeNode {
109                int value ;
110               TreeNode leftNode;
111               TreeNode rightNode;
112 
113                public TreeNode(int value) {
114                       this.value = value;
115                       this.leftNode = null;
116                       this.rightNode = null;
117               }
118        }
119 
120         public static void main(String[] args) {
121                int[] content = { 50, 35, 27, 45, 40, 48, 78, 56, 90 };
122 
123               BinaryTree tree = new BinaryTree(content);
124               System. out.println("前序遍历:" );
125               tree.preOrder(tree. rootNode);
126               System. out.println("\n中序遍历:" );
127               tree.inOrder(tree. rootNode);
128               System. out.println("\n后序遍历:" );
129               tree.postOrder(tree. rootNode);
130 
131               System. out.println("\n\n开始搜索:" );
132                boolean isFind = tree.findTree(tree.rootNode, 48);
133               System. out.println("是否搜索到" + 48 + ":" + isFind);
134               
135               System. out.println("\n进行排序:" );
136               tree.sort();
137        }
138 }
View Code
  
  看下运行结果:
 1 前序遍历:
 2 [50][35][27][45][40][48][78][56][90]
 3 中序遍历:
 4 [27][35][40][45][48][50][56][78][90]
 5 后序遍历:
 6 [27][40][48][45][35][56][90][78][50]
 7 
 8 开始搜索:
 9 共搜索3次
10 是否搜索到48:true
11 
12 进行排序:
13 [27][35][40][45][48][50][56][78][90]
View Code

 

相关文章:

  • 2021-11-30
  • 2022-01-19
  • 2021-06-05
  • 2022-02-28
  • 2021-06-13
  • 2021-07-17
  • 2021-12-03
  • 2022-02-16
猜你喜欢
  • 2021-07-13
  • 2021-11-06
  • 2021-06-23
  • 2021-09-28
相关资源
相似解决方案