(转)算法系列 ——遍历所有控件的递归和非递归实现
题目描述
给出布局的根节点,要求不使用递归的方式将所有类型为Button的控件背景设置为红色。
分析
对于Android中的布局来说,有两种类型的节点,一种是ViewGroup布局,另外一种是View控件,按照类似树形结构来组织(注意,不是二叉树)。
对于控件的遍历,可以转化为对树的遍历。对树的遍历有递归方式和非递归的方式,非递归方式又可以分为深度优先遍历和广度优先遍历。
实现
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rootView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="10dp" android:background="#abcdef" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#156ec7" android:orientation="horizontal" android:padding="10dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:text="文本1" android:textColor="#ffffff" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:text="文本2" android:textColor="#ffffff" /> </LinearLayout> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按钮1" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#5d9726" android:padding="10dp"> <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按钮2" /> <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/btn" android:padding="5dp" android:text="文本3" android:textColor="#ffffff" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/btn" android:layout_toRightOf="@id/tv" android:padding="5dp" android:text="文本4" android:textColor="#ffffff" /> </RelativeLayout> </LinearLayout>
界面效果和对应的树结构如下:
其中有颜色的节点类型为viewGroup
布局 | 抽象树结构 |
具体算法实现
以下方式实现了三种方式的遍历结果,读者可以参考。
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ViewGroup root = (ViewGroup) findViewById(R.id.rootView); travelTree3(root); } //递归遍历树 private void travelTree1(View root) { if (root instanceof ViewGroup) { int childCount = ((ViewGroup) root).getChildCount(); for (int i = 0; i < childCount; i++) { travelTree1(((ViewGroup) root).getChildAt(i)); } } else if (root instanceof View) { Log.i("visitView", root.toString()); if (root instanceof Button) root.setBackgroundColor(Color.parseColor("#ff0000")); } } //非递归广度遍历,利用队列数据结构 private void travelTree2(View root) { ArrayDeque queue = new ArrayDeque(); queue.addLast(root); while (!queue.isEmpty()) { //取得队头 View front = (View) queue.getFirst(); //如果为viewGroup则使子节点入队列 if (front instanceof ViewGroup) { int childCount = ((ViewGroup) front).getChildCount(); for (int i = 0; i < childCount; i++) { queue.addLast(((ViewGroup) front).getChildAt(i)); } } //如果队头为View类型,输出 else if (front instanceof View) Log.i("visitView", front.toString()); //队头出队 queue.pollFirst(); } } //非递归深度遍历,利用栈数据结构 private void travelTree3(View root) { ArrayDeque stack = new ArrayDeque(); stack.addLast(root); while (!stack.isEmpty()) { //取得栈顶 View top = (View) stack.getLast(); //出栈 stack.pollLast(); //如果为viewGroup则使子节点入栈 if (top instanceof ViewGroup) { int childCount = ((ViewGroup) top).getChildCount(); for (int i = childCount - 1; i >= 0; i--) { stack.addLast(((ViewGroup) top).getChildAt(i)); } } //如果栈顶为View类型,输出 else if (top instanceof View) Log.i("visitView", top.toString()); } } }
相关推荐
清溪算法君老号 2020-06-27
oXiaoChong 2020-06-20
baike 2020-05-09
Tips 2020-05-03
steeven 2020-11-10
Tips 2020-10-14
nongfusanquan0 2020-08-18
yedaoxiaodi 2020-07-26
pengkingli 2020-06-25
yishujixiaoxiao 2020-06-25
清溪算法 2020-06-21
RememberMePlease 2020-06-17
nurvnurv 2020-06-05
SystemArchitect 2020-06-02
码墨 2020-05-29
清溪算法 2020-05-27
choupiaoyi 2020-05-27
清溪算法 2020-05-25
bluewelkin 2020-05-19
dbhllnr 2020-05-15