Java中樹和樹的幾種常規遍歷方法


其中包含有先序遍歷、中序遍歷、后序遍歷以及廣度優先遍歷四種遍歷樹的方法:

  1 package com.ietree.basic.datastructure.tree.binarytree;
  2 
  3 import java.util.ArrayDeque;
  4 import java.util.ArrayList;
  5 import java.util.List;
  6 import java.util.Queue;
  7 
  8 /**
  9  * Created by ietree
 10  * 2017/5/1
 11  */
 12 public class ThreeLinkBinTree<E> {
 13 
 14     public static class TreeNode {
 15 
 16         Object data;
 17         TreeNode left;
 18         TreeNode right;
 19         TreeNode parent;
 20 
 21         public TreeNode() {
 22 
 23         }
 24 
 25         public TreeNode(Object data) {
 26             this.data = data;
 27         }
 28 
 29         public TreeNode(Object data, TreeNode left, TreeNode right, TreeNode parent) {
 30             this.data = data;
 31             this.left = left;
 32             this.right = right;
 33             this.parent = parent;
 34         }
 35 
 36     }
 37 
 38     private TreeNode root;
 39 
 40     // 以默認的構造器創建二叉樹
 41     public ThreeLinkBinTree() {
 42         this.root = new TreeNode();
 43     }
 44 
 45     // 以指定根元素創建二叉樹
 46     public ThreeLinkBinTree(E data) {
 47         this.root = new TreeNode(data);
 48     }
 49 
 50     /**
 51      * 為指定節點添加子節點
 52      *
 53      * @param parent 需要添加子節點的父節點的索引
 54      * @param data   新子節點的數據
 55      * @param isLeft 是否為左節點
 56      * @return 新增的節點
 57      */
 58     public TreeNode addNode(TreeNode parent, E data, boolean isLeft) {
 59 
 60         if (parent == null) {
 61             throw new RuntimeException(parent + "節點為null, 無法添加子節點");
 62         }
 63         if (isLeft && parent.left != null) {
 64             throw new RuntimeException(parent + "節點已有左子節點,無法添加左子節點");
 65         }
 66         if (!isLeft && parent.right != null) {
 67             throw new RuntimeException(parent + "節點已有右子節點,無法添加右子節點");
 68         }
 69 
 70         TreeNode newNode = new TreeNode(data);
 71         if (isLeft) {
 72             // 讓父節點的left引用指向新節點
 73             parent.left = newNode;
 74         } else {
 75             // 讓父節點的left引用指向新節點
 76             parent.right = newNode;
 77         }
 78         // 讓新節點的parent引用到parent節點
 79         newNode.parent = parent;
 80         return newNode;
 81     }
 82 
 83     // 判斷二叉樹是否為空
 84     public boolean empty() {
 85         // 根據元素判斷二叉樹是否為空
 86         return root.data == null;
 87     }
 88 
 89     // 返回根節點
 90     public TreeNode root() {
 91         if (empty()) {
 92             throw new RuntimeException("樹為空,無法訪問根節點");
 93         }
 94         return root;
 95     }
 96 
 97     // 返回指定節點(非根節點)的父節點
 98     public E parent(TreeNode node) {
 99         if (node == null) {
100             throw new RuntimeException("節點為null,無法訪問其父節點");
101         }
102         return (E) node.parent.data;
103     }
104 
105     // 返回指定節點(非葉子)的左子節點,當左子節點不存在時返回null
106     public E leftChild(TreeNode parent) {
107         if (parent == null) {
108             throw new RuntimeException(parent + "節點為null,無法添加子節點");
109         }
110         return parent.left == null ? null : (E) parent.left.data;
111     }
112 
113     // 返回指定節點(非葉子)的右子節點,當右子節點不存在時返回null
114     public E rightChild(TreeNode parent) {
115         if (parent == null) {
116             throw new RuntimeException(parent + "節點為null,無法添加子節點");
117         }
118         return parent.right == null ? null : (E) parent.right.data;
119     }
120 
121     // 返回該二叉樹的深度
122     public int deep() {
123         // 獲取該樹的深度
124         return deep(root);
125     }
126 
127     // 這是一個遞歸方法:每一棵子樹的深度為其所有子樹的最大深度 + 1
128     private int deep(TreeNode node) {
129         if (node == null) {
130             return 0;
131         }
132         // 沒有子樹
133         if (node.left == null && node.right == null) {
134             return 1;
135         } else {
136             int leftDeep = deep(node.left);
137             int rightDeep = deep(node.right);
138             // 記錄其所有左、右子樹中較大的深度
139             int max = leftDeep > rightDeep ? leftDeep : rightDeep;
140             // 返回其左右子樹中較大的深度 + 1
141             return max + 1;
142         }
143     }
144 
145     // 實現先序遍歷
146     // 1、訪問根節點
147     // 2、遞歸遍歷左子樹
148     // 3、遞歸遍歷右子樹
149     public List<TreeNode> preIterator() {
150         return preIterator(root);
151     }
152 
153     private List<TreeNode> preIterator(TreeNode node) {
154 
155         List<TreeNode> list = new ArrayList<TreeNode>();
156         // 處理根節點
157         list.add(node);
158 
159         // 遞歸處理左子樹
160         if (node.left != null) {
161             list.addAll(preIterator(node.left));
162         }
163 
164         // 遞歸處理右子樹
165         if (node.right != null) {
166             list.addAll(preIterator(node.right));
167         }
168 
169         return list;
170 
171     }
172 
173     // 實現中序遍歷
174     // 1、遞歸遍歷左子樹
175     // 2、訪問根節點
176     // 3、遞歸遍歷右子樹
177     public List<TreeNode> inIterator() {
178         return inIterator(root);
179     }
180 
181     private List<TreeNode> inIterator(TreeNode node) {
182 
183         List<TreeNode> list = new ArrayList<TreeNode>();
184 
185         // 遞歸處理左子樹
186         if (node.left != null) {
187             list.addAll(inIterator(node.left));
188         }
189 
190         // 處理根節點
191         list.add(node);
192 
193         // 遞歸處理右子樹
194         if (node.right != null) {
195             list.addAll(inIterator(node.right));
196         }
197 
198         return list;
199 
200     }
201 
202     // 實現后序遍歷
203     // 1、遞歸遍歷左子樹
204     // 2、遞歸遍歷右子樹
205     // 3、訪問根節點
206     public List<TreeNode> postIterator() {
207         return postIterator(root);
208     }
209 
210     private List<TreeNode> postIterator(TreeNode node) {
211 
212         List<TreeNode> list = new ArrayList<TreeNode>();
213 
214         // 遞歸處理左子樹
215         if (node.left != null) {
216             list.addAll(postIterator(node.left));
217         }
218 
219         // 遞歸處理右子樹
220         if (node.right != null) {
221             list.addAll(postIterator(node.right));
222         }
223 
224         // 處理根節點
225         list.add(node);
226 
227         return list;
228 
229     }
230 
231     // 實現廣度優先遍歷
232     // 廣度優先遍歷又稱為按層遍歷,整個遍歷算法先遍歷二叉樹的第一層(根節點),再遍歷根節點的兩個子節點(第二層),以此類推
233     public List<TreeNode> breadthFirst() {
234 
235         Queue<TreeNode> queue = new ArrayDeque<TreeNode>();
236         List<TreeNode> list = new ArrayList<TreeNode>();
237         if (root != null) {
238             // 將根元素加入“隊列”
239             queue.offer(root);
240         }
241         while (!queue.isEmpty()) {
242             // 將該隊列的“隊尾”的元素添加到List中
243             list.add(queue.peek());
244             TreeNode p = queue.poll();
245             // 如果左子節點不為null,將它加入“隊列”
246             if (p.left != null) {
247                 queue.offer(p.left);
248             }
249             // 如果右子節點不為null,將它加入“隊列”
250             if (p.right != null) {
251                 queue.offer(p.right);
252             }
253         }
254         return list;
255     }
256 
257 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM