基于红黑树的骨架提取Java

前面有提到基于Mat变换的骨架提取,然而在实际的应用中处理稍微大点的图片的时候耗时较长就是个问题了,于是针对这个问题寻找了另外一种方法——基于红黑树的骨架提取,这种方法明显处理速度要快一些。

基于红黑树的骨架提取的思路如下:

1,对输入的二值图像进行延拓(直白的说就是在图像的外边界加一圈白点),得到二值图像P;

2,针对骨架提取有8种结构类型(S0~S7)的待删除点。骨架提取的过程实际上就是不断的找符合这8种结构的待删除点,删除待删除点。初始化8个空的红黑树结构T0~T7,初始化current=0,每一个红黑树对应存储一种类别的待删除点,例如:T0存储符合S0结构的待删除点,T1存储符合S1结构的待删除点......;

3,初始化标记矩阵L;

4,遍历P,确定所有待移除点及其对应的红黑树索引值,将待移除点的索引值插入对应的红黑树,;

5,判断T0~T7是否都为空,如果是,则已完成骨架提取,返回P。如果不是全为空,初始化round=0,到下一步;

6,判断round是否等于8,如果是返回第5步,如果不是,到下一步;

7,用数组R记录Tcurrent中的所有区域点索引值,清空Tcurrent,更新current=current+1;

8,根据R更新P,L和T0~T7,round=round+1,返回第6步。

  1 package com.example.lenovo.linehough;
  2
  3 import android.graphics.Color;
  4
  5 public class Framework {
  6     int width;
  7     int height;
  8     int Fpn;
  9     int[] pixels;
 10     int[] treeValue;
 11     GRBTree[] grbTree;
 12     int currentTree;
 13     TList[] L;
 14     int[] InfluencedPnt;
 15     int lutTreeNum[] = {
 16             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 17             0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 2,
 18             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 19             0, 0, 1, 1, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 1,
 20             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 21             0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 1, 1,
 22             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 23             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 24             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 25             0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
 26             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 27             1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 28             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 29             0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 0, 0, 0, 0,
 30             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 31             1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 32             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 33             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 34             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 35             0, 0, 1, 1, 1, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0,
 36             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 37             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 38             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 39             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 40             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 41             0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
 42             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 43             1, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 44             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 45             1, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0,
 46             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 47             2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0
 48     };
 49
 50     int lutTreeIdx1[] = {
 51             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 52             0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3, 3, 0, 0, 3, 2,
 53             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 54             0, 0, 5, 5, 0, 0, 5, 2, 0, 0, 0, 0, 0, 0, 0, 2,
 55             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 56             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 3,
 57             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 58             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 59             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 60             0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
 61             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 62             7, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 63             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 64             0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
 65             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 66             7, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 67             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 68             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 69             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 70             0, 0, 5, 5, 6, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0,
 71             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 72             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 73             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 74             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 75             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 76             0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
 77             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 78             7, 0, 0, 0, 6, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 79             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 80             4, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
 81             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 82             4, 0, 0, 0, 7, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0
 83     };
 84
 85     int lutTreeIdx2[] = {
 86             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 87             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
 88             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 89             0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0,
 90             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 91             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0,
 92             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 93             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 94             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 95             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 96             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 97             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 98             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 99             0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
100             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
101             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
102             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
103             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
104             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105             0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,
106             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
107             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
109             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
110             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
111             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
112             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
113             0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
114             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
115             0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,
116             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
117             7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
118     };
119
120     public Framework() {
121
122     }
123
124     //TList建立一个矩阵,矩阵元素包含TreeIndex,Visited两个字段;
125     // TreeIndex记录待移除点对应的红黑树序号(0~7),TreeIndex为-1时,该点为非移除点;Visited标记点是否被访问过了
126     public class TList {
127         int TreeIndex;
128         int Visited;
129
130         public TList() {
131             this.TreeIndex = -1;
132             this.Visited = 0;
133         }
134     }
135
136     //提取骨架
137     public int[] getFramework(int w, int h, int[] inputs) {
138         width = w;
139         height = h;
140         pixels = new int[width * height];
141         //黑色为1,白色为0
142         for (int y = 0; y < height; y++) {
143             for (int x = 0; x < width; x++) {
144                 if (inputs[y * width + x] == Color.BLACK)
145                     pixels[y * width + x] = 1;
146                 else pixels[y * width + x] = 0;
147             }
148         }
149         //新建8个红黑树对象
150         grbTree = new GRBTree[8];
151         for (int i = 0; i <= 7; i++) {
152             grbTree[i] = new GRBTree();
153         }
154         currentTree = 0;
155
156         L = new TList[width * height];
157         for (int i = 0; i < width * height; i++) {
158             L[i] = new TList();
159         }
160         //第一次遍历二值化图像
161         FirstMatchTree();
162
163         //当所有的树里面不再插入结点的时候,说明骨架已经生成,即n0~n7都为0
164         while (grbTree[0].root != null || grbTree[1].root != null || grbTree[2].root != null || grbTree[3].root != null ||
165                 grbTree[4].root != null || grbTree[5].root != null || grbTree[6].root != null || grbTree[7].root != null) {
166             for (int round = 0; round <= 7; round++) {
167                 treeValue = new int[width * height];
168                 //前序遍历树currentTree的移除点索引值,将它们先存放在数组treeValue里面
169                 treeValue = grbTree[currentTree].preOrder(width, height);
170                 //存放在树currentTree里面的移除点总数
171                 int valueCount = grbTree[currentTree].getiCount();
172
173                 //再清空树currentTree里面的数据,root置为null
174                 grbTree[currentTree].Free();
175
176                 currentTree++;
177                 if (currentTree == 8) currentTree = 0;
178
179                 //更新pixels,L
180                 for (int i1 = 0; i1 < valueCount; i1++) {
181                     int pntIndex = treeValue[i1];
182                     pixels[pntIndex] = 0;
183                     L[pntIndex].TreeIndex = -1;//TreeIndex为-1时,该点为非移除点
184                     L[pntIndex].Visited = -1;//Visited为-1时,表明该点已成为非待移除点
185                 }
186                 //遍历数组treeValue,InfluencedPnt记录受影响的领域点坐标,Fpn为受影响点的个数
187                 InfluencedPnt = new int[width * height];
188                 Fpn = 0;
189                 for (int i1 = 0; i1 < valueCount; i1++) {
190                     int pntIndex = treeValue[i1];
191                     //查找移除点的8领域点
192                     for (int i2 = -1; i2 <= 1; i2++) {
193                         for (int i3 = -1; i3 <= 1; i3++) {
194                             if (i2 == 0 && i3 == 0) continue;
195                             //8个领域点的下标索引值index
196                             int index = pntIndex + i2 * width + i3;
197                             if (index < 0) index = 0;
198                             if (index > width * height - 1)
199                                 index = width * height - 1;
200                             //该领域点为白点直接退出
201                             if (pixels[index] == 0) continue;
202                             //Visite为1时,表明该领域点已被访问过,直接退出;
203                             if (L[index].Visited == 1) continue;
204                             else {
205                                 L[index].Visited = 1;
206                                 InfluencedPnt[Fpn] = index;
207                                 Fpn++;
208                             }
209                             //更新树T0到T7,只要检测到8领域点是待移除点的话,首先将它从原来的树里面删除;不是的话,不操作;
210                             // 之后再根据该领域点的3*3结构(可能发生变化)来判断它是否是待移除点,以及它该插入到哪棵红黑树里面
211                             int treeindex = L[index].TreeIndex;
212                             if (treeindex >= 0)
213                                 grbTree[treeindex].Delete(index);
214                             //获取领域点index的3*3结构
215                             int[] b = new int[9];
216                             for (int i4 = -1; i4 <= 1; i4++) {
217                                 for (int i5 = -1; i5 <= 1; i5++) {
218                                     int index8 = index + i5 * width + i4;
219                                     if (index8 < 0) index = 0;
220                                     if (index8 > width * height - 1)
221                                         index8 = width * height - 1;
222                                     b[(i4 + 1) * 3 + (i5 + 1)] = pixels[index8];
223                                 }
224                             }
225                             //计算领域点index对应的lutTreeNum的下标值lutValue
226                             int lutValue = 0;
227                             for (int i = 0; i <= 8; i++) {
228                                 if (b[i] == 1)
229                                     lutValue += Math.pow(2, i);
230                             }
231                             //将待移除的领域点index插入对应的红黑树k里面,并将k值记录到L中
232                             int k = Put(index, lutValue);
233                             if (k >= 0) L[index].TreeIndex = k;
234                             else L[index].TreeIndex = -1;
235                         }
236                     }
237                 }
238
239                 for (int i = 0; i < Fpn; i++) {
240                     int f = InfluencedPnt[i];
241                     L[f].Visited = 0;
242                 }
243
244             }
245         }
246         //while循环结束,再也没有移除点
247         for (int y = 0; y < height; y++) {
248             for (int x = 0; x < width; x++) {
249                 if (pixels[y * width + x] == 1) inputs[y * width + x] = Color.BLACK;
250                 else inputs[y * width + x] = Color.WHITE;
251             }
252         }
253         return inputs;
254     }
255
256     private void FirstMatchTree() {
257         //第一次遍历二值化图像,currentTree=0,把待移除点插入对应的红黑树里面
258         for (int y = 1; y < height - 1; y++) {
259             for (int x = 1; x < width - 1; x++) {
260                 int pntIndex = y * width + x;
261                 //是白色点的话直接退出本次循环,检测下一个点
262                 if (pixels[pntIndex] == 0) continue;
263                 //检测像素点的3*3领域结构,组成a[8]a[7]...a[1]a[0]的九位二进制数
264                 int[] a = new int[9];
265                 for (int i = -1; i <= 1; i++) {
266                     for (int j = -1; j <= 1; j++) {
267                         a[(i + 1) * 3 + (j + 1)] = pixels[(y + j) * width + (x + i)];
268                     }
269                 }
270                 //通过上面的九位二进制数,计算出该像素点对应于lutTreeNum的下标值
271                 int lutValue = 0;
272                 for (int i = 0; i <= 8; i++) {
273                     if (a[i] == 1)
274                         lutValue += Math.pow(2, i);
275                 }
276                 //k为树的序号数,pntIndex为待移除点的话,k的范围为0到7;不是待移除点的话,k为-1
277                 int k = Put(pntIndex, lutValue);
278                 if (k >= 0) L[pntIndex].TreeIndex = k;
279                 else L[pntIndex].TreeIndex = -1;
280             }
281         }
282     }
283
284     private int GetTreeIndex(int lutValue) {
285         if (lutTreeNum[lutValue] == 0)
286             return -1;
287
288         if (lutTreeNum[lutValue] == 1)
289             return lutTreeIdx1[lutValue];
290
291         if (currentTree > lutTreeIdx1[lutValue] && currentTree <= lutTreeIdx2[lutValue])
292             return lutTreeIdx2[lutValue];
293
294         return lutTreeIdx1[lutValue];
295     }
296
297     private int Put(int pntIndex, int lutValue) {
298         int ti = GetTreeIndex(lutValue);
299
300         if (ti < 0)
301             return -1;
302
303         grbTree[ti].Insert(pntIndex);
304
305         return ti;
306     }
307
308     private void Delete(int pntIndex, int lutValue) {
309         int ti = GetTreeIndex(lutValue);
310
311         if (ti < 0 || ti == currentTree)
312             return;
313
314         grbTree[ti].Delete(pntIndex);
315     }
316
317
318 }
时间: 2024-09-30 07:24:59

基于红黑树的骨架提取Java的相关文章

基于Mat变换的骨架提取Java

针对一副二值图像,区域内的点只有背景点(白点,0值)和前景点(黑点,1值).对于给定区域的像素点逐次应用两个基本步骤,以提取骨架: step1,如果一个像素点满足下列4个条件,那么将它标记为要删除的点: (1)2<=N(p1)<=6,其中N(p1)=p2+p3+p4+...+p8+p9; (2)T(p1)=1,其中T(p1)是以p2,p3,...,p8,p9,p2的次序旋转,从0到1的变换次数; (3)p2*p4*p6=0; (4)p4*p6*p8=0. step2,条件(1)(2)不变,但是

TreeMap:是基于红黑树的Map接口的实现

> TreeMap:是基于红黑树的Map接口的实现. 红黑树:平衡二叉树 取出时,可以有三种方式:前序遍历,中序遍历,后序遍历 >排序: A 自然排序  --TreeMap无参构造 TreeMap<key类型,value类型> map= new TreeMap<key类型,value类型>(); //key类应当实现Comparable接口,并重写hashCode()和equals()方法 B 比较器排序-TreeMap 比较器有参构造 TreeMap<key类型

红黑树深入剖析及Java实现

红黑树是平衡二叉查找树的一种.为了深入理解红黑树,我们需要从二叉查找树开始讲起. BST 二叉查找树(Binary Search Tree,简称BST)是一棵二叉树,它的左子节点的值比父节点的值要小,右节点的值要比父节点的值大.它的高度决定了它的查找效率. 在理想的情况下,二叉查找树增删查改的时间复杂度为O(logN)(其中N为节点数),最坏的情况下为O(N).当它的高度为logN+1时,我们就说二叉查找树是平衡的. BST的查找操作 T key = a search key Node root

红黑树的理解与Java实现

前言 前段时间在研究 JDK1.8 的 hashmap 源码,看到 put 方法的插入环节,遇到了红黑树,不得不停止阅读源码的过程,因为还没掌握红黑树是无法完全读透 hashmap 源码的.红黑树作为一种数据结构,它被应用得非常多,可能很多人不认识它,但其实它已经在默默为我们的代码在发光发热.例如,你只要在 Java 中用到 map,基本上就是在用红黑树(当元素个数到达八个时链表转红黑树). PS:在看这篇文章前,必须先了解普通的二叉查找树和平衡查找树(AVL)树.2-3-4树.不然看起来会非常

红黑树(附完整C代码)

版权声明:原创不易,转载请注明转自weewqrer 红黑树 红黑树简介 首先红黑树是一棵二叉搜索树,它在每个结点上增加了一个存储位来表示结点的颜色,可以是RED或者BLACK.通过对一条从根节点到NIL叶节点(指空结点或者下面说的哨兵)的简单路径上各个结点在颜色进行约束,红黑树确保没有一条路径会比其他路径长出2倍,因而是近似平衡的. 用途 红黑树和AVL树一样都对插入时间.删除时间和查找时间提供了最好可能的最坏情况担保.对于查找.插入.删除.最大.最小等动态操作的时间复杂度为O(lgn).常见的

Java集合详解6:TreeMap和红黑树

Java集合详解6:TreeMap和红黑树 初识TreeMap 之前的文章讲解了两种Map,分别是HashMap与LinkedHashMap,它们保证了以O(1)的时间复杂度进行增.删.改.查,从存储角度考虑,这两种数据结构是非常优秀的.另外,LinkedHashMap还额外地保证了Map的遍历顺序可以与put顺序一致,解决了HashMap本身无序的问题. 尽管如此,HashMap与LinkedHashMap还是有自己的局限性----它们不具备统计性能,或者说它们的统计性能时间复杂度并不是很好才

Java集合详解6:这次,从头到尾带你解读Java中的红黑树

<Java集合详解系列>是我在完成夯实Java基础篇的系列博客后准备开始写的新系列. 这些文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下Star.fork哈 文章首发于我的个人博客: www.how2playlife.com 什么是红黑树 首先,什么是红黑树呢? 红黑树是一种"平衡的"二叉查找树,它是一种经典高效的算法,能够保证

《 常见算法与数据结构》平衡查找树(2)——红黑树(附动画)

本系列文章主要介绍常用的算法和数据结构的知识,记录的是<Algorithms I/II>课程的内容,采用的是"算法(第4版)"这本红宝书作为学习教材的,语言是java.这本书的名气我不用多说吧?豆瓣评分9.4,我自己也认为是极好的学习算法的书籍. 通过这系列文章,可以加深对数据结构和基本算法的理解(个人认为比学校讲的清晰多了),并加深对java的理解. 红黑树介绍 红黑树是一种简单的实现2-3树的数据结构,它方便的把我们之前实现的二叉搜索树改造成了一棵2-3树.它的核心思想

TreeMap 红黑树实现

TreeMap 是一个有序的key-value集合,它是通过 红黑树 实现的. TreeMap 继承于AbstractMap,所以它是一个Map,即一个key-value集合. TreeMap 实现了NavigableMap,Cloneable和Serializable接口. TreeMap的基本操作 containsKey.get.put 和 remove 的时间复杂度是 log(n) . 首先是TreeMap的构造方法: public TreeMap() { comparator = nul