Problem
Asymmetric binary tree search algorithm
Ideas
Binary Tree search is a common search algorithm for dynamic data. This article is based on the translation of the following address and the appropriate modification according to my understanding. The code is implemented in python.
Address: http://www.laurentluce.com/posts/binary-search-tree-library-in-python/comment-page-1/
Binary Tree search Definition
For definition content, see Wikipedia: http://en.wikipedia.org/wiki/Binary_tree
Here is Chinese: http://zh.wikipedia.org/wiki/%E4%BA%8C%E5%85%83%E6%90%9C%E5%B0%8B%E6%A8%B9
Description of Binary Tree:
The nature of binary tree search:
- If the left subtree of any node is not empty, the value of all nodes on the left subtree is smaller than the value of its root node;
- If the right subtree of any node is not empty, the value of all nodes on the right subtree is greater than the value of its root node;
- The left and right subtree of any node are also binary lookup trees.
- No node with the same key value (no duplicate nodes ).
Compared with other data structures, the binary search tree has lower time complexity in searching and inserting. Is O (log n ). A binary search tree is a basic data structure used to construct more abstract data structures, such as collections, et, and associated arrays.
Although the worst efficiency of the Binary Search Tree is O (n), it supports dynamic query, and there are many two versions of the binary search tree can make the tree as O (logn), such as SBT, AVL, red/black tree, etc.
Binary Tree search using python
The binary tree shown in the following figure is used as an example to describe the search algorithm.
Node class
Create a class named "Node" as the Binary Tree Node structure, which includes three variables: left branch, right branch, and Node data.
Class Node: "tree left and right branches" def _ init _ (self, data): "Node Structure" self. left = None self. right = None self. data = data
For example, create a node with an integer of 8. Because only one node is created, the left and right branches are None.
root = Node(8)
In this way, we can see a tree with only one node.
Insert Method
Now there is a bald tree. To have branches and leaves, you must use the data insertion method to add new nodes and data.
Def insert (self, data): "insert node data" if data <self. data: if self. left is None: self. left = Node (data) else: self. left. insert (data) elif data> self. data: if self. right is None: self. right = Node (data) else: self. right. insert (data)
After performing the preceding operations, you can add branches and leaves (left and right branches and node data) of the tree as follows ).
root.insert(3)root.insert(10)root.insert(1)
When the second node data 3 is added, the program will:
- Step 1: root will call insert (). The parameter is data = 3.
- Step 2: Compare 3 and 8 (existing root nodes), and 3 is smaller than 8. And the left branch of the tree is still None, so a new node is created on the left.
Add the data of the third node 10. The program will:
- The first step is the same as the previous step, except data = 10
- Step 2: If 10 is greater than 8 and the right side is None, it is used as the node data of the new branch on the right.
Add data 1 of the fourth node. The program will:
- Step 1: Same as before, data = 1
- Step 2: 1 is less than 8, so it should be placed on the left branch of the tree;
- Step 3: The left branch already has subnode 3. This node calls the insert () method again, and 1 is smaller than 3. Therefore, 1 is used as the subnode of 3 and placed on the left side of the original "None.
In this way, a tree is formed.
Continue adding node data
root.insert(6)root.insert(4)root.insert(7)root.insert(14)root.insert(13)
Final tree
Traverse tree
This method is used to find a node in the tree. If yes, the node is returned. Otherwise, None is returned. For convenience, the parent node is also returned.
Def lookup (self, data, parent = None): "traversal Binary Tree" if data <self. data: if self. left is None: return None, None return self. left. lookup (data, self) elif data> self. data: if self. right is None: return None, None return self. right. lookup (data, self) else: return self, parent
Test it. Find the node with 6 data.
node, parent = root.lookup(6)
After lookup () is called, the program will do this:
Delete Method
Delete node data. The Code is as follows:
Def delete (self, data): "delete node" "node, parent = self. lookup (data) # existing node if node is not None: children_count = node. children_count () # determine the number of subnodes if children_count = 0: # if there are no subnodes under the node, delete if parent. left is node: parent. left = None else: parent. right = None del node elif children_count = 1: # if a subnode exists, move it up to replace the node (this node disappears) if node. left: n = node. left else: n = node. right if parent: if parent. left is node: parent. left = n else: parent. right = n del node else: # if there are two subnodes, determine all the leaves under the node. parent = node successor = node. right while successor. left: parent = successor. left node. data = successor. data if parent. left = successor: parent. left = successor. right else: parent. right = successor. right
In the preceding method, after obtaining the number of subnodes under the current node, You Need To determine three conditions.
- If there are no child nodes, delete them directly.
- If there is a subnode, move the next subnode to the current node, that is, replace
- If there are two subnodes, You need to judge the data of your own nodes and sort the data from the new nodes.
The method for counting the number of subnodes is used in the preceding method. The Code is as follows:
Def children_count (self): "" Number of subnodes "cnt = 0 if self. left: cnt + = 1 if self. right: cnt + = 1 return cnt
Example 1: delete a node whose data is 1. It is a subnode of 3 and no subnode is behind 1.
root.delete(1)
Example 2: delete a node with data of 14, which is a sub-node with 10. It has a unique sub-node with 13 and 13 replaced.
root.delete(14)
Example 3: a complex node that deletes node data as 3. It has two nodes, and two nodes and four or seven under Node 6. A temporary variable successor is required to query subnodes under Node 3, replace Level 1 subnode 6 with Level 3 left test node data 4 (the data must be smaller than parent node 6) with the current node 3 to maintain the binary tree structure. For example:
root.delete(3)
Compare two Binary Trees
In the method of comparing two binary trees, if one node (leaf) is different from the other tree, False is returned, including the absence of corresponding leaves.
Def compare_trees (self, node): "Two Comparison" if node is None: return False if self. data! = Node. data: return False res = True if self. left is None: if node. left: return False else: res = self. left. compare_trees (node. left) if res is False: return False if self. right is None: if node. right: return False else: res = self. right. compare_trees (node. right) return res
For example, compare tree (, 10) and tree (, 11)
# Root2 is the root of tree (, 11) # root is the root of tree (, 10). compare_trees (root2)
Execute the above Code and the program will go like this:
Print tree
Print the binary tree in a certain order. No parameter is required. The method is to first left and then right (left and less than right ).
Def print_tree (self): "number of printed content in sequence" if self. left: self. left. print_tree () print self. data, if self. right: self. right. print_tree ()
Perform the following operations:
root.print_tree()
Output: 1, 3, 4, 6, 7, 8, 10, 13, 14
Generator containing all Tree Elements
Creating a generator that contains all tree elements is sometimes necessary. Considering the memory issue, it is not necessary to generate a data list of all nodes in real time. Instead, the value of the next node returned by this method is required each time it is called. Therefore, if you use it to return an object and stop there, the function will continue to return the value through the yield keyword during the next method call. In this case, you must use a stack instead of recursion.
Def tree_data (self): "binary tree data structure" "stack = [] node = self while stack or node: if node: stack. append (node) node = node. left else: node = stack. pop () yield node. data node = node. right
For example, you can use a loop to get the tree:
for data in root.tree_data(): print data
The program will import the data into and out of the stack according to the atom on the left and right, and take out the values in sequence and return the results.