Java中二叉排序樹

  1 package com.ietree.basic.datastructure.tree;
  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 SortedBinTree<T extends Comparable> {
 13 
 14     static class Node {
 15 
 16         Object data;
 17         Node parent;
 18         Node left;
 19         Node right;
 20 
 21         public Node(Object data, Node parent, Node left, Node right) {
 22             this.data = data;
 23             this.parent = parent;
 24             this.left = left;
 25             this.right = right;
 26         }
 27 
 28         public String toString() {
 29             return "[data=" + data + "]";
 30         }
 31 
 32         public boolean equals(Object obj) {
 33             if (this == obj) {
 34                 return true;
 35             }
 36             if (obj.getClass() == Node.class) {
 37                 Node target = (Node) obj;
 38                 return data.equals(target.data) && left == target.left && right == target.right && parent == target.parent;
 39             }
 40             return false;
 41         }
 42 
 43     }
 44 
 45     private Node root;
 46 
 47     // 兩個構造器用於建立排序二叉樹
 48     public SortedBinTree() {
 49         root = null;
 50     }
 51 
 52     public SortedBinTree(T o) {
 53         root = new Node(o, null, null, null);
 54     }
 55 
 56     // 添加節點
 57     public void add(T ele) {
 58         // 若是根節點爲null
 59         if (root == null) {
 60             root = new Node(ele, null, null, null);
 61         } else {
 62             Node current = root;
 63             Node parent = null;
 64             int cmp = 0;
 65             // 搜索合適的葉子節點,以該葉子節點爲父節點添加新節點
 66             do {
 67                 parent = current;
 68                 cmp = ele.compareTo(current.data);
 69                 // 若是新節點的值大於當前節點的值
 70                 if (cmp > 0) {
 71                     // 以右子節點做爲當前節點
 72                     current = current.right;
 73                 } else {
 74                     // 若是新節點的值小於當前節點的值
 75                     // 以左節點做爲當前節點
 76                     current = current.left;
 77                 }
 78             }
 79             while (current != null);
 80             // 建立新節點
 81             Node newNode = new Node(ele, parent, null, null);
 82             // 若是新節點的值大於父節點的值
 83             if (cmp > 0) {
 84                 // 新節點做爲父節點的右子節點
 85                 parent.right = newNode;
 86             } else {
 87                 // 若是新節點的值小於父節點的值
 88                 // 新節點做爲父節點的左子節點
 89                 parent.left = newNode;
 90             }
 91         }
 92     }
 93 
 94     // 刪除節點
 95     public void remove(T ele) {
 96         // 獲取要刪除的節點
 97         Node target = getNode(ele);
 98         if (target == null) {
 99             return;
100         }
101         // 左、右子樹爲空
102         if (target.left == null && target.right == null) {
103             // 被刪除節點是根節點
104             if (target == root) {
105                 root = null;
106             } else {
107                 // 被刪除節點是父節點的左子節點
108                 if (target == target.parent.left) {
109                     // 將target的父節點的left設爲null
110                     target.parent.left = null;
111                 } else {
112                     // 將target的父節點的right設爲null
113                     target.parent.right = null;
114                 }
115                 target.parent = null;
116             }
117         } else if (target.left == null && target.right != null) {
118             // 左子樹爲空,右子樹不爲空
119             // 被刪除節點是根節點
120             if (target == root) {
121                 root = target.right;
122             } else {
123                 // 被刪除節點是父節點的左子節點
124                 if (target == target.parent.left) {
125                     // 讓target的父節點的left指向target的右子樹
126                     target.parent.left = target.right;
127                 } else {
128                     // 讓target的父節點的right指向target的右子樹
129                     target.parent.right = target.right;
130                 }
131                 // 讓target的右子樹的parent指向target的parent
132                 target.right.parent = target.parent;
133             }
134         } else if (target.left != null && target.right == null) {
135             // 左子樹不爲空,右子樹爲空
136             // 被刪除節點是根節點
137             if (target == root) {
138                 root = target.left;
139             } else {
140                 // 被刪除節點是父節點的左子節點
141                 if (target == target.parent.left) {
142                     // 讓target的父節點的left指向target的左子樹
143                     target.parent.left = target.left;
144                 } else {
145                     // 讓target的父節點的right指向target的左子樹
146                     target.parent.right = target.left;
147                 }
148                 // 讓target的左子樹的parent指向target的parent
149                 target.left.parent = target.parent;
150             }
151         } else {
152             // 左、右子樹都不爲空
153             // leftMaxNode用於保存target節點的左子樹中值最大的節點
154             Node leftMaxNode = target.left;
155             // 搜索target節點的左子樹中值最大的節點
156             while (leftMaxNode.right != null) {
157                 leftMaxNode = leftMaxNode.right;
158             }
159             // 從原來的子樹中刪除leftMaxNode節點
160             leftMaxNode.parent.right = null;
161             // 讓leftMaxNode的parent指向target的parent
162             leftMaxNode.parent = target.parent;
163             // 被刪除節點是父節點的左子節點
164             if (target == target.parent.left) {
165                 // 讓target的父節點的left指向leftMaxNode
166                 target.parent.left = leftMaxNode;
167             } else {
168                 // 讓target的父節點的right指向leftMaxNode
169                 target.parent.right = leftMaxNode;
170             }
171             leftMaxNode.left = target.left;
172             leftMaxNode.right = target.right;
173             target.parent = target.left = target.right = null;
174         }
175     }
176 
177     // 根據給定的值搜索節點
178     public Node getNode(T ele) {
179         // 從根節點開始搜索
180         Node p = root;
181         while (p != null) {
182             int cmp = ele.compareTo(p.data);
183             // 若是搜索的值小於當前p節點的值
184             if (cmp < 0) {
185                 // 向左子樹搜索
186                 p = p.left;
187             } else if (cmp > 0) {
188                 // 若是搜索的值大於當前p節點的值
189                 // 向右子樹搜索
190                 p = p.right;
191             } else {
192                 return p;
193             }
194         }
195         return null;
196     }
197 
198     // 廣度優先遍歷
199     public List<Node> breadthFirst() {
200 
201         Queue<Node> queue = new ArrayDeque<Node>();
202         List<Node> list = new ArrayList<Node>();
203         if (root != null) {
204             // 將根元素入「隊列」
205             queue.offer(root);
206         }
207         while (!queue.isEmpty()) {
208             // 將該隊列的「隊尾」的元素添加到List中
209             list.add(queue.peek());
210             Node p = queue.poll();
211             // 若是左子節點不爲null,將它加入「隊列」
212             if (p.left != null) {
213                 queue.offer(p.left);
214             }
215             // 若是右子節點不爲null,將它加入「隊列」
216             if (p.right != null) {
217                 queue.offer(p.right);
218             }
219         }
220         return list;
221     }
222 
223 }

測試類:java

 1 package com.ietree.basic.datastructure.tree;
 2 
 3 /**
 4  * Created by ietree
 5  * 2017/5/1
 6  */
 7 public class SortedBinTreeTest {
 8 
 9     public static void main(String[] args) {
10 
11         SortedBinTree<Integer> tree = new SortedBinTree<Integer>();
12 
13         // 添加節點
14         tree.add(5);
15         tree.add(20);
16         tree.add(10);
17         tree.add(3);
18         tree.add(8);
19         tree.add(15);
20         tree.add(30);
21 
22         System.out.println(tree.breadthFirst());
23         // 刪除節點
24         tree.remove(20);
25         System.out.println(tree.breadthFirst());
26 
27     }
28 
29 }

程序輸出:測試

[[data=5], [data=3], [data=20], [data=10], [data=30], [data=8], [data=15]]
[[data=5], [data=3], [data=15], [data=10], [data=30], [data=8]]

採用廣度優先法則來遍歷排序二叉樹獲得的不是有序序列,採用中序遍從來遍歷排序二叉樹才能夠獲得有序序列。this

相關文章
相關標籤/搜索