1. 程式人生 > >資料結構之樹結構

資料結構之樹結構

資料結構之樹結構

 

 

樹結構:一種描述非線性層次關係的資料結構 ,其中重要的是樹的概念。

樹:n個數據結點的集合,在該集合中包含一個根結點。根結點之下分佈著一些互不交叉的子集合,
       這些子集合也就是根結點的子樹。
 
樹結構的基本特徵:
        在一個樹結構中,有且僅有一個結點沒有直接前驅,這個結點就是樹的根結點;
        除根結點外,其餘每個結點有且僅有一個直接前驅;
        每個結點可以有任意多個直接後繼。

  1 Java程式碼實現:
  2 
  3 
  4 
  5 /**
  6  * 非線性儲存結構 -> 連結串列實現的二叉查詢樹
  7  * 
  8  * 初始化 計算表長 獲取結點 查詢結點 插入結點 刪除結點
  9  * 
 10  * @see java.util.TreeMap
 11  * 
 12  */
 13 public class Tree<T> {
 14 
 15     /** 根結點 */
 16     private Node<T> root;
 17 
 18     /** 比較器 */
 19     private
final Comparator<T> comparator; 20 21 /** 樹的容量 */ 22 private int size = 0; 23 24 /** 初始化 */ 25 public Tree() { 26 comparator = null; 27 } 28 29 /** 初始化 */ 30 public Tree(Comparator<T> comparator) { 31 this.comparator = comparator; 32 }
33 34 /** 初始化 */ 35 public Tree(Comparator<T> comparator, Collection<T> c) { 36 this.comparator = comparator; 37 addAll(c); 38 } 39 40 /* 新增集合中所有元素到樹 */ 41 private boolean addAll(Collection<T> c) { 42 boolean modified = false; 43 for (T t : c) 44 if (add(t)) 45 modified = true; 46 return modified; 47 } 48 49 /** 新增結點 */ 50 public boolean add(T t) { 51 Node<T> n = root; 52 if (n == null) { 53 root = new Node<>(t, null); 54 size++; 55 return true; 56 } 57 Node<T> parent = null; 58 int m = 0; 59 Comparator<? super T> c = comparator; 60 if (c != null) { 61 do { 62 parent = n; 63 m = c.compare(n.data, t); 64 if (m < 0) { 65 n = n.left; 66 } else if (m > 0) { 67 n = n.right; 68 } else { 69 // 相同型別元素的處理: 不能儲存兩個相同的資料. 70 } 71 } while (n != null); 72 } else { 73 @SuppressWarnings("unchecked") 74 Comparable<? super T> cc = (Comparable<? super T>) t; 75 do { 76 parent = n; 77 m = cc.compareTo(n.data); 78 if (m < 0) { 79 n = n.left; 80 } else if (m > 0) { 81 n = n.right; 82 } else { 83 // 相同型別元素的處理: 不能儲存兩個相同的資料. 84 } 85 } while (n != null); 86 } 87 Node<T> e = new Node<>(t, parent); 88 if (m < 0) 89 parent.left = e; 90 else 91 parent.right = e; 92 93 size++; 94 return true; 95 } 96 97 /** 刪除結點 */ 98 public boolean remove(T t) { 99 Node<T> n = getNode(t); 100 if (n == null) 101 return false; 102 deleteNode(n); 103 return true; 104 } 105 106 /** 樹中是否存在某個物件 */ 107 public boolean contains(T o) { 108 return getNode(o) == null ? false : true; 109 } 110 111 /* 獲得樹結點 */ 112 private final Node<T> getNode(T t) { 113 @SuppressWarnings("unchecked") 114 Comparable<? super T> c = (Comparable<? super T>) t; 115 Node<T> n = root; 116 while (n != null) { // 樹的遍歷 117 int m = c.compareTo(n.data); 118 if (m < 0) 119 n = n.left; 120 else if (m > 0) 121 n = n.right; 122 else 123 return n; // 找到儲存資料的節點 124 } 125 return null; 126 } 127 128 /* 刪除樹結點 */ 129 private final void deleteNode(Node<T> node) { 130 size--; 131 if (node.left != null && node.right != null) { 132 Node<T> n = successor(node); // 返回後繼結點 133 node.data = n.data; 134 node = n; 135 } 136 137 Node<T> r = (node.left != null ? node.left : node.right); 138 if (r != null) { // node.left != null 139 r.parent = node.parent; // 連線節點replacement到node的parent 140 if (node.parent == null) // node就是root 141 root = r; // 刪除node,replacement變為root 142 else if (node == node.parent.left) 143 node.parent.left = r; 144 else 145 node.parent.right = r; 146 147 node.left = node.right = node.parent = null; // 刪除 148 } else if (node.parent == null) { // 149 root = null; 150 } else { // 151 if (node.parent != null) { 152 if (node == node.parent.left) 153 node.parent.left = null; 154 else if (node == node.parent.right) 155 node.parent.right = null; 156 node.parent = null; 157 } 158 } 159 } 160 161 /* 查詢後繼結點 */ 162 private static final <T> Node<T> successor(Node<T> node) { 163 if (node == null) { 164 return null; 165 } else if (node.right != null) { 166 Node<T> p = node.right; 167 while (p.left != null) 168 p = p.left; 169 return p; 170 } else { 171 Node<T> p = node.parent; 172 Node<T> c = node; 173 while (p != null && c == p.right) { 174 c = p; 175 p = p.parent; 176 } 177 return p; 178 } 179 } 180 181 /* 查詢前任結點 */ 182 private static final <T> Node<T> predecessor(Node<T> node) { 183 if (node == null) { 184 return null; 185 } else if (node.left != null) { 186 Node<T> n = node.left; 187 while (n.right != null) 188 n = n.right; 189 return n; 190 } else { 191 Node<T> n = node.parent; 192 Node<T> c = node; 193 while (n != null && c == n.left) { 194 c = n; 195 n = n.parent; 196 } 197 return n; 198 } 199 } 200 201 /* 遍歷子樹 */ 202 String orderTree(Node<T> node) { // 使用遞迴,中序遍歷子樹. 203 if (node != null) { 204 orderTree(node.left); 205 System.out.print(node.data + ", "); 206 orderTree(node.right); 207 } 208 return null; 209 } 210 211 /** 二叉樹的結點 */ 212 private static final class Node<T> { 213 214 T data; // 資料 215 Node<T> parent; // 父親結點 216 Node<T> left; // 左子樹(小) 217 Node<T> right; // 右子樹(大) 218 219 Node(T data,Node<T> parent) { 220 this.data = data; 221 this.parent = parent; 222 } 223 224 @Override 225 public int hashCode() { 226 return data.hashCode(); 227 } 228 229 @Override 230 public boolean equals(Object obj) { 231 return data.equals(obj); 232 } 233 234 public String toString() { 235 return data.toString(); 236 } 237 238 } 239 240 /** 樹迭代器 */ 241 final class TreeIterator implements Iterator<Node<T>> { 242 243 Node<T> next; // 下一個 244 Node<T> prev; // 上一個 245 246 TreeIterator(Node<T> first) { 247 next = first; 248 prev = null; 249 } 250 251 @Override 252 public boolean hasNext() { 253 return next != null; 254 } 255 256 @Override 257 public Node<T> next() { 258 Node<T> e = next; 259 if (e == null) 260 throw new NoSuchElementException(); 261 next = successor(e); 262 prev = e; 263 return e; 264 } 265 266 public Node<T> prev() { 267 Node<T> e = next; 268 if (e == null) 269 throw new NoSuchElementException(); 270 next = predecessor(e); 271 prev = e; 272 return e; 273 } 274 275 } 276 277 /** 獲得迭代器 */ 278 public Iterator<Node<T>> iterator() { 279 Node<T> first = root; 280 while (first.left != null) //找到第一個節點,即最小值節點. 281 first = first.left; 282 return new TreeIterator(first); 283 } 284 285 /** 計算容量 */ 286 public int size() { 287 return size; 288 } 289 290 /** 字串輸出 */ 291 public String toString() { 292 Iterator<Node<T>> i = iterator(); 293 if (!i.hasNext()) 294 return "{}"; 295 StringBuilder builder = new StringBuilder(); 296 builder.append('{'); 297 for (;;) { 298 Node<T> e = i.next(); 299 builder.append(e.data); 300 if (!i.hasNext()) 301 return builder.append('}').toString(); 302 builder.append(',').append(' '); 303 } 304 } 305 306 }