數據結構系列之2-3-4樹的插入、查找、刪除和遍歷完整版源代碼實現與分析(dart語言實現)

  本文屬於原創,轉載請註明來源。  html

  在上一篇博文中,詳細介紹了2-3樹的操做(具體地址:http://www.javashuo.com/article/p-zfutpyan-du.html),那麼對於更多教科書上更爲廣泛的2-3-4樹,在這裏也給出 樹的定義、節點的定義、插入、查找、刪除和遍歷等操做的源代碼實現。函數

  關於2-3-4樹的文字定義,網上不少,可自行百度,這裏再也不重複論述。但看了不少博文,關於插入等操做的實現較多,基本上沒有實現刪除操做的。所以本博文給出完整版的2-3-4樹的插入、刪除、查找及遍歷等源代碼。spa

  另,2-3-4樹代碼的實現,與2-3樹很是相似,故關於代碼的分析,請參考2-3樹(http://www.javashuo.com/article/p-zfutpyan-du.html)的介紹,這裏僅給出簡要說明。rest

  若是節點容許的最大元素數量超過3個,非葉子節點最大孩子數量超過4個,就成了多叉樹,後續有機會分享一下一個關於8叉樹的實現。code

  本代碼由dart語言實現,關於dart,一門相似Java、JavaScript的語言,也是如今比較流行的flutter的後臺語言,有興趣的同窗能夠去dart官網瞭解:htm

  https://dart.devblog

閒話少說,上代碼。遞歸

 1 // 樹的定義 2-3-4樹  2 class QuaternaryTree<E extends Comparable<E>> {  3 QuaterNode<E> _root;  4 int _elementsCount;  5  6 factory QuaternaryTree.of(Iterable<Comparable<E>> elements) {  7 var tree = QuaternaryTree<E>();  8 for (var e in elements) tree.insert(e);  9 return tree;  10  }  11  12 QuaternaryTree() : _elementsCount = 0;  13  14 int get elementsCount => _elementsCount;  15 QuaterNode<E> get root => _root;  16  17 // 計算樹高  18 int get height {  19 var h = 0, c = root;  20 while (c != null) {  21 h++;  22 c = c.isNotLeaf ? c.branches[0] : null;  23  }  24 return h;  25  }  26  27 bool get isEmpty => _root == null;  28  29 bool contains(E value) => find(value) != null;  30  31 // 查找樹中是否存在某個值  32 // 若找到,返回包含此值的樹節點,不然返回null  33 QuaterNode<E> find(E value) {  34 var c = root;  35 while (c != null) {  36 var i = 0;  37 while (i < c.size && c.items[i].compareTo(value) < 0) i++;  38 if (i < c.size && c.items[i] == value) break;  39 c = c.isNotLeaf ? c.branches[i] : null;  40  }  41 return c;  42  }  43  44 // 插入新的值,若是值已經存在,則不作任何操做  45 // 插入始終在葉子節點進行  46 void insert(E value) {  47 var c = root, i = 0;  48 while (c != null) {  49 i = 0;  50 while (i < c.size && c.items[i].compareTo(value) < 0) i++;  51 if (i < c.size && c.items[i] == value) return;  52 if (c.isLeaf) break;  53 c = c.branches[i];  54  }  55 if (c != null) {  56  c.items.insert(i, value);  57  58 // 判斷插入後是否須要修復  59 if (c.isOverflow) _fixAfterIns(c);  60 } else {  61 _root = QuaterNode([value]);  62  }  63 _elementsCount++;  64  }  65  66 // 刪除指定值  67  bool delete(E value) {  68 // 首先查找該值  69 var d = find(value);  70 // 若不存在,直接返回  71 if (d == null) return false;  72  73 // 查找該值在節點中的索引順序  74 var i = d.find(value);  75  76 // 若是節點不是葉子節點,則用後繼節點的值替代該值  77 // 這樣刪除操做將轉移爲刪除葉子節點的值  78 if (d.isNotLeaf) {  79 var s = _successor(d.branches[i + 1]);  80 d.items[i] = s.items[0];  81 d = s;  82 i = 0;  83  }  84  d.items.removeAt(i);  85 _elementsCount--;  86  87 // 根據2-3-4樹的定義,節點不能爲空,所以判斷刪除後是否須要修復  88 if (d.items.isEmpty) _fixAfterDel(d);  89 return true;  90  }  91  92 // 遍歷樹  93 void traverse(void func(List<E> items)) {  94 if (!isEmpty) _traverse(_root, func);  95  }  96  97 // 插入修復  98 // 注意,插入修復時,採用節點分裂的形式進行修復;  99 // 分裂出來的新的父節點須要被上層節點吸取(若是存在上層節點的話) 100 void _fixAfterIns(QuaterNode<E> c) { 101 while (c != null && c.isOverflow) { 102 var t = _split(c); 103 c = t.parent != null ? _absorb(t) : null; 104  } 105  } 106 107 // 節點分裂,因爲分裂->吸取,可能會遞歸分裂; 108 // 所以須要注意根節點的更新判斷以及子節點的處理; 109 QuaterNode<E> _split(QuaterNode<E> c) { 110 var mid = c.size ~/ 2, 111 l = QuaterNode._internal(c.items.sublist(0, mid)), 112 nc = QuaterNode._internal(c.items.sublist(mid, mid + 1)), 113 r = QuaterNode._internal(c.items.sublist(mid + 1)); 114  nc.branches.addAll([l, r]); 115 l.parent = r.parent = nc; 116 117 nc.parent = c.parent; 118 if (c.parent != null) { 119 var i = 0; 120 while (c.parent.branches[i] != c) i++; 121 c.parent.branches[i] = nc; 122 } else { 123 _root = nc; 124  } 125 if (c.isNotLeaf) { 126  l.branches 127 ..addAll(c.branches.getRange(0, mid + 1)) 128 ..forEach((b) => b.parent = l); 129  r.branches 130 ..addAll(c.branches.getRange(mid + 1, c.branches.length)) 131 ..forEach((b) => b.parent = r); 132  } 133 return nc; 134  } 135 136 // 上層節點吸取新分裂出來的節點,以保持樹的平衡 137 QuaterNode<E> _absorb(QuaterNode<E> c) { 138 var i = 0, p = c.parent; 139 while (p.branches[i] != c) i++; 140  p.items.insertAll(i, c.items); 141 p.branches.replaceRange(i, i + 1, c.branches); 142 c.branches.forEach((b) => b.parent = p); 143 return p; 144  } 145 146 // 查找後繼節點 147 QuaterNode<E> _successor(QuaterNode<E> p) { 148 while (p.isNotLeaf) p = p.branches[0]; 149 return p; 150  } 151 152 // 刪除修復 153 void _fixAfterDel(QuaterNode<E> d) { 154 if (d == root) { 155 _root = null; 156 } else { 157 var ct = 0; 158 while (d.size < (1 << ct + 1) - 1 && d.parent != null) { 159 // 塌縮父節點 160  _collapse(d.parent); 161 d = d.parent; 162 ct++; 163  } 164 165 // 若是塌縮到了樹的根,則樹高減1 166 // if (d.size < (1 << ct + 1) - 1) ct--; 167 if (d == root) ct--; 168 169 // 修剪多餘的值 170 var rest = _prune(d, (1 << ct + 1) - 1); 171 172 // 從新展開 173  _expand(d, ct); 174 175 // 將剛纔修剪掉的多餘的值從新插入樹 176 for (var e in rest) insert(e); 177  } 178  } 179 180 // 樹的塌縮函數,注意遞歸塌縮 181 void _collapse(QuaterNode<E> p) { 182 if (p.isLeaf) return; 183 for (var i = p.branches.length - 1; i >= 0; i--) { 184  _collapse(p.branches[i]); 185  p.items.insertAll(i, p.branches[i].items); 186  } 187  p.branches.clear(); 188  } 189 190 // 修剪,保留知足展開爲滿二叉樹的最小數量的值 191 List<E> _prune(QuaterNode<E> d, int least) { 192 var t = d.size ~/ least, rest = <E>[]; 193 if (t < 2) { 194  rest.addAll(d.items.getRange(least, d.size)); 195  d.items.removeRange(least, d.size); 196 } else { 197 // 跳躍修剪,以保證二次插入時分裂的次數較少 198 var list = <E>[]; 199 for (var i = 0; i < d.size; i++) { 200 if (i % t == 0 && list.length < least) 201  list.add(d.items[i]); 202 else 203  rest.add(d.items[i]); 204  } 205 d.items = list; 206  } 207 _elementsCount -= rest.length; 208 return rest; 209  } 210 211 // 遞歸展開修剪後的節點,ct表明展開的層數或高度 212 void _expand(QuaterNode<E> p, int ct) { 213 if (ct == 0) return; 214 p = _split(p); 215 for (var b in p.branches) _expand(b, ct - 1); 216  } 217 218 void _traverse(QuaterNode<E> r, void f(List<E> items)) { 219  f(r.items); 220 for (var b in r.branches) _traverse(b, f); 221  } 222 } 223 224 class QuaterNode<E extends Comparable<E>> { 225 static final int capacity = 3; 226 List<E> items; 227 List<QuaterNode<E>> branches; 228 QuaterNode<E> parent; 229 230 factory QuaterNode(List<E> elements) { 231 if (elements.length > capacity) throw StateError('too many elements.'); 232 return QuaterNode._internal(elements); 233  } 234 235 QuaterNode._internal(List<E> elements) 236 : items = [], 237 branches = [] { 238  items.addAll(elements); 239  } 240 241 int get size => items.length; 242 bool get isOverflow => size > capacity; 243 bool get isLeaf => branches.isEmpty; 244 bool get isNotLeaf => !isLeaf; 245 246 bool contains(E value) => items.contains(value); 247 int find(E value) => items.indexOf(value); 248 249 String toString() => items.toString(); 250 }

 -end-索引

相關文章
相關標籤/搜索