python实现二分搜索树以及改进后的AVL Tree
来源:互联网 发布:南财网络教育平台 编辑:程序博客网 时间:2024/05/29 10:25
二分搜索树讲解
python代码:
class TreeNode(object): def __init__(self, key, val, parent=None, left_child=None, right_child=None): self.key = key self.val = val self.parent = parent # 指向该节点的双亲节点 self.left_child = left_child self.right_child = right_child def is_left_child(self): return self.parent and self.parent.left_child == self def is_right_child(self): return self.parent and self.parent.right_child == self def is_root(self): return not self.parent def is_leaf(self): return not (self.left_child or self.right_child) def has_any_child(self): return self.left_child or self.right_child def has_both_childs(self): return self.left_child and self.right_child def find_successor(self): """ 寻找该节点的successor successor必须是leaf node 或 只有一个子节点 """ if self.right_child: return self.right_child.find_min() elif self.is_left_child(): return self.parent else: self.parent.right_child = None succ = self.parent.find_successor() self.parent.right_child = self return succ def find_min(self): # 寻找该节点及其子节点中key最小的节点 current_node = self while current_node.left_child: current_node = current_node.left_child return current_node def splice(self): """ 去除successor,并将其子节点和其双亲节点嫁接 """ if self.is_leaf(): if self.is_left_child(): self.parent.left_child = None else: self.parent.right_child = None elif self.has_any_child(): if self.left_child: if self.is_left_child(): self.parent.left_child = self.left_child else: self.parent.right_child = self.left_child self.left_child.parent = self.parent else: if self.is_left_child(): self.parent.left_child = self.right_child else: self.parent.right_child = self.right_child self.right_child.parent = self.parent def replace_node_data_childs(self, new_key, new_val, new_left_child, new_right_child): self.key = new_key self.val = new_val self.left_child = new_left_child self.right_child = new_right_child def __iter__(self): if self: if self.left_child: for elem in self.left_child: yield elem yield self.key if self.right_child: for elem in self.right_child: yield elemclass BinSearchTree(object): def __init__(self, root=None): self.root = None self._size = 0 def __len__(self): return self._size def __setitem__(self, k, v): if self.root: self.__put(k, v, self.root) else: # the search tree is empty self.root = TreeNode(k, v) self._size += 1 def __put(self, k, v, current_node): if k < current_node.key: if current_node.left_child: self.__put(k, v, current_node.left_child) else: current_node.left_child = TreeNode(k, v, parent=current_node) elif k > current_node.key: if current_node.right_child: self.__put(k, v, current_node.right_child) else: current_node.right_child = TreeNode(k, v, parent=current_node) else: # the k == current_node.key current_node.val = v def __getitem__(self, k): if self._size > 1: item = self.__get(k, self.root) if item: return self.__get(k, self.root).val else: return None elif self._size == 1 and self.root.key == k: return self.root.val else: return None # if self.root: # if self._size == 1: # the tree only has root node # if self.root.key == k: # return self.root.val # else: # return None # else: # if self.__get(k, self.root): # return self.__get(k, self.root).val # return None # else: # the tree is empty # return None def __get(self, k, current_node): if not current_node: return None elif k == current_node.key: return current_node elif k < current_node.key: return self.__get(k, current_node.left_child) else: return self.__get(k, current_node.right_child) # if current_node: # if k < current_node.key: # return self.__get(k, current_node.left_child) # elif k > current_node.key: # return self.__get(k, current_node.right_child) # else: # return current_node # else: # the tree doesn't has the key # return None def __contains__(self, k): if self.__getitem__(k): return True else: return False def __delitem__(self, k): if self._size > 1: del_node = self.__get(k, self.root) if del_node: self.__remove(del_node) self._size -= 1 else: raise KeyError('Error, key not in tree') elif self._size == 1 and self.root.val == k: self.root = None self._size -= 1 else: raise KeyError('Error, key not in tree') def __remove(self, del_node): # if the node that would be deleted has no childs if del_node.is_leaf(): if del_node.is_left_child(): del_node.parent.left_child = None else: del_node.parent.right_child = None elif del_node.has_both_childs(): successor = del_node.find_successor() successor.splice() del_node.key = successor.key del_node.val = successor.val else: # the node that would be deleted has a child if del_node.left_child: if del_node.is_left_child(): del_node.parent.left_child, del_node.left_child.parent = \ del_node.left_child, del_node.parent elif del_node.is_right_child(): del_node.parent.right_child, del_node.left_child.parent = \ del_node.left_child, del_node.parent else: # the node that would be deleted is root node del_node.replace_node_data_childs(del_node.left_child.key, del_node.left_child.val, del_node.left_child.left_child, del_node.left_child.right_child) else: # the node that would be deleted has right child if del_node.is_left_child(): del_node.parent.left_child, del_node.right_child.parent = \ del_node.right_child, del_node.parent elif del_node.is_right_child(): del_node.parent.right_child, del_node.right_child.parent = \ del_node.right_child, del_node.parent else: del_node.replace_node_data_childs(del_node.right_child.key, del_node.right_child.val, del_node.right_child.left_child, del_node.right_child.right_child) def __iter__(self): if self.root: for k in self.root: yield k else: raise KeyError('the tree is empty')if __name__ == '__main__': mytree = BinSearchTree() # setitem mytree[3] = "red" mytree[4] = "blue" mytree[6] = "yellow" mytree[2] = "at" mytree[5] = "green" # delete item del mytree[4] for k in mytree: print(k)
AVL树讲解
python代码:
from bin_search_tree import BinSearchTree, TreeNodeclass AVLTreeNode(TreeNode): def __init__(self, key, val, parent=None, left_child=None, right_child=None): super().__init__(key, val, parent, left_child, right_child) self.balance_factor = 0class AVLTree(BinSearchTree): def __init__(self, root=None): super().__init__(root) def __setitem__(self, k, v): """ override the super().__setitem__ """ if self.root: self.__put(k, v, self.root) else: # the search tree is empty self.root = AVLTreeNode(k, v) self._size += 1 def __put(self, k, v, current_node): """ override the super().__put """ if k < current_node.key: if current_node.left_child: self.__put(k, v, current_node.left_child) else: current_node.left_child = AVLTreeNode(k, v, parent=current_node) self.__update_balance(current_node.left_child) elif k > current_node.key: if current_node.right_child: self.__put(k, v, current_node.right_child) else: current_node.right_child = AVLTreeNode(k, v, parent=current_node) self.__update_balance(current_node.right_child) else: current_node.val = v def __update_balance(self, current_node): if current_node.balance_factor < -1 or \ current_node.balance_factor > 1: self.__rebalance(current_node) return if current_node.parent != None: if current_node.is_left_child(): current_node.parent.balance_factor += 1 elif current_node.is_right_child(): current_node.parent.balance_factor -= 1 if current_node.parent.balance_factor != 0: self.__update_balance(current_node.parent) def __rebalance(self, current_node): if current_node.balance_factor < -1: # need left rotation if current_node.right_child.balance_factor > 0: self.__right_rotate(current_node.right_child) self.__left_rotate(current_node) elif current_node.balance_factor > 1: # need right rotation if current_node.left_child.balance_factor < 0: self.__left_rotate(current_node.left_child) self.__right_rotate(current_node) def __left_rotate(self, rot_root): """ the node's balance factor < -1 """ # 将rot root的右子节点设为new root new_root = rot_root.right_child # 将new root的左子节点设置为rot root的右子节点 rot_root.right_child = new_root.left_child if new_root.left_child: new_root.left_child.parent = rot_root # 将new root的双亲节点设置为rot root的双亲节点 new_root.parent = rot_root.parent if rot_root.is_root(): self.root = new_root else: if rot_root.is_left_child(): rot_root.parent.left_child = new_root else: rot_root.parent.right_child = new_root # 将rot root的双亲节点设置为new root(rot root为new root的左子节点) new_root.left_child = rot_root rot_root.parent = new_root # critical steps # update the balance factor both of rot root and new root rot_root.balance_factor = rot_root.balance_factor + 1 - min(new_root.balance_factor, 0) new_root.balance_factor = new_root.balance_factor + 1 + max(rot_root.balance_factor, 0) def __right_rotate(self, rot_root): """ the node's balance factor > 1 """ # 将rot root的左子节点设为new root new_root = rot_root.left_child # 将new root的右子节点设置为rot root的左子节点 rot_root.left_child = new_root.right_child if new_root.right_child: new_root.right_child.parent = rot_root # 将new root的双亲节点设置为rot root的双亲节点 new_root.parent = rot_root.parent if rot_root.is_root(): self.root = new_root else: if rot_root.is_left_child(): rot_root.parent.left_child = new_root else: rot_root.parent.right_child = new_root # 将rot root的双亲节点设置为new root(rot root为new root的右子节点) new_root.right_child = rot_root rot_root.parent = new_root # critical steps # update the balance factor both of rot root and new root rot_root.balance_factor = rot_root.balance_factor - 1 + min(new_root.balance_factor, 0) new_root.balance_factor = new_root.balance_factor - 1 - max(rot_root.balance_factor, 0)if __name__ == '__main__': mytree = AVLTree() # setitem mytree[3] = "red" mytree[4] = "blue" mytree[6] = "yellow" # mytree[2] = "at" # mytree[5] = "green" print('root:%s|balance_factor:%s' % (mytree.root.key, mytree.root.balance_factor)) print('root.left_child:%s' % mytree.root.left_child.key) print('root.right_child:%s' % mytree.root.right_child.key)
阅读全文
0 0
- python实现二分搜索树以及改进后的AVL Tree
- AVL树C++实现以及(递归函数)非递归改进
- AVL Tree 的实现
- AVL Tree 的实现
- AVL树的C++实现 Implement of AVL tree
- AVL树的python实现
- 二叉搜索树-AVL树的实现
- 二分搜索树的实现
- PAT1066 Root of AVL Tree 平衡二叉树的实现
- 二叉树、二叉搜索树、AVL树的java实现
- AVL Tree 的C/C++ 实现
- 红黑树C++实现以及与AVL树的区别
- 改进后的多线程文件搜索
- java平衡搜索树AVL实现
- AVL树的实现
- AVL树的实现
- AVL树的实现
- AVL 树的实现
- 内存地址问题总结
- oracle统计
- unity InputFied.onValuechanged 应用
- JS监听手机返回键
- c语言基础(一)
- python实现二分搜索树以及改进后的AVL Tree
- hdoj 1013 Digital roots (陷阱水题)
- 数据样本不平衡问题处理方法
- cc1plus.exe: out of memory allocating 3077145919 bytes
- js拼装html无法触发事件
- ios 导航栏的一些理解
- JBPN的认识和特点、工作流程、发展状况
- 数据库设计三范式(nomorlization)
- spring源码@Async阅读笔记