22
33> 在 Android 下,UI 的布局结构,对标到数据结构中,本质就是一个由 View 和 ViewGroup 组成的多叉树结构。其中 View 只能作为叶子节点...
44
5- ![ ] ( https://ask.qcloudimg.com/http-save/yehe-4918971/l3vo6ivz7k.png?imageView2/2/w/1620 )
5+
66
77一. 审题
88-----
1313
1414在 Android 下,UI 的布局结构,对标到数据结构中,本质就是一个由 View 和 ViewGroup 组成的多叉树结构。其中 View 只能作为叶子节点,而 ViewGroup 是可以存在子节点的。
1515
16- ![ img ] ( https://ask.qcloudimg.com/http-save/yehe-4918971 /bjr5eltscx.png)
16+ ![ bjr5eltscx ] ( images /bjr5eltscx.png)
1717
1818上图就是一个典型的 ViewTree 的结构,而想要遍历这个 ViewTree,还需要用到两个 ViewGroup 的方法。
1919
2727
2828### 2.1 递归实现
2929
30- ###
31-
32- ![ ] ( https://ask.qcloudimg.com/http-save/yehe-4918971/p4d2w4jaop.png )
30+ ![ p4d2w4jaop] ( images/p4d2w4jaop-4372882.png )
3331
3432** 当一个大问题,可以被拆分成多个小问题,并且分解后的小问题,和大问题相比,只是数据规模不同,求解思路完全一致的问题,非常适合递归来实现。**
3533
36- ```
34+ ``` kotlin
3735fun recursionPrint (root : View ) {
3836 printView(root)
3937 if (root is ViewGroup ) {
@@ -47,15 +45,15 @@ fun recursionPrint(root: View) {
4745
4846递归确实可以很清晰的实现功能,但是它有一个致命的问题,当递归深度过深的时候,会爆栈。反应在程序上,就是会抛出 ` StackOverflowError ` 这个异常。
4947
50- 面试的时候,面试者解决问题的思路,使用了递归思想,通常都会很自然的问问 JVM 的栈帧,以及为什么会出现 StackOverflowError 异常。
48+ 面试的时候,面试者解决问题的思路,** 使用了递归思想,通常都会很自然的问问 JVM 的栈帧,以及为什么会出现 StackOverflowError 异常。**
5149
5250当然这不是本文的重点,大家了解一下即可。
5351
5452简单来说,每启动一个线程,JVM 都会为其分配一个 Java 栈,每调用一个方法,都会被封装成一个栈帧,进行** 压栈** 操作,当方法执行完成之后,又会执行** 弹栈** 操作。而每个栈帧中,当前调用的方法的一些局部变量、动态连接,以及返回地址等数据。
5553
5654Java 栈和数据结构的栈结构一样,有两个操作,压栈(入栈)、弹栈(出栈),是一个先入后出(FILO)的结构。这一块的东西,延伸出来就比较多了,你可以简单的理解为调用方法就会压栈,方法执行完会弹栈。
5755
58- ![ ] ( https://ask.qcloudimg.com/http-save/yehe-4918971 /h10ztydlyk.png)
56+ ![ h10ztydlyk ] ( images /h10ztydlyk.png)
5957
6058每次方法的调用,执行压栈的操作,但是每个栈帧,都是要消耗内存的。一旦超过了限制,就会爆掉,抛出 StackOverflowError。
6159
@@ -69,17 +67,17 @@ Java 栈和数据结构的栈结构一样,有两个操作,压栈(入栈)
6967
7068广度优先的过程,就是对每一层节点依次访问,访问完了再进入下一层。就是** 按树的深度,一层层的遍历访问** 。
7169
72- ![ ] ( https://ask.qcloudimg.com/http-save/yehe-4918971 /id06rtebmp.png)
70+ ![ id06rtebmp ] ( images /id06rtebmp.png)
7371
7472ABCDEFGHI 就是上图这个多叉树,使用广度优先算法的遍历结果。
7573
7674** 广度优先非常适合用先入先出的队列来实现** ,每次子 View 都入队尾,而从对头取新的 View 进行处理。
7775
78- ![ ] ( https://ask.qcloudimg.com/http-save/yehe-4918971 /47589gl30c.png)
76+ ![ 47589gl30c ] ( images /47589gl30c.png)
7977
8078代码如下:
8179
82- ```
80+ ``` kotlin
8381fun breadthFirst (root : View ){
8482 val viewDeque = LinkedList <View >()
8583 var view = root
@@ -105,19 +103,19 @@ fun breadthFirst(root :View){
105103
106104深度优先的过程,就是对每个可能的分支路径,深度到叶子节点,并且每个节点只访问一次。
107105
108- ![ ] ( https://ask.qcloudimg.com/http-save/yehe-4918971 /s6m19use7k.png)
106+ ![ s6m19use7k ] ( images /s6m19use7k.png)
109107
110108ADIHCBGFE 就是上图这个多叉树,使用深度优先算法的遍历结果。
111109
112110在实现上,** 深度优先非常适合用先入后出的栈来实现** 。逻辑不复杂,直接上执行时,栈的数据变换。
113111
114- ![ ] ( https://ask.qcloudimg.com/http-save/yehe-4918971 /uvzzx8usas.png)
112+ ![ uvzzx8usas ] ( images /uvzzx8usas.png)
115113
116- ![ ] ( https://ask.qcloudimg.com/http-save/yehe-4918971 /qw4k131pwx.png)
114+ ![ qw4k131pwx ] ( images /qw4k131pwx.png)
117115
118116代码实现如下:
119117
120- ```
118+ ``` kotlin
121119fun depthFirst (root : View ){
122120 val viewDeque = LinkedList <View >()
123121 var view = root
@@ -145,5 +143,3 @@ fun depthFirst(root :View){
145143其实这道题,还有一些变种,例如统计 ViewGroup 子 View 的数量、分层打印 ViewTree、查找 ID 为 Xxx 的 View 等,有兴趣可以试着写写代码。
146144
147145算法题就是这样,有一些是考验编码能力,另一些是解决问题的思路,多思考多写,才是正道。
148-
149- 本文参与[ 腾讯云自媒体分享计划] ( https://cloud.tencent.com/developer/support-plan ) ,欢迎正在阅读的你也加入,一起分享。
0 commit comments