Tree data structure (I)

Tree data structure (I)

I. Overview

  The main contents include basic concepts of tree, binary tree (balanced binary tree, complete binary tree, full binary tree), search tree (binary search trees, balanced search trees, AVL trees, splay trees, (2,4) tree, red-black tree), practical application (a, b) tree, B trees tree data structure

Second, the basic knowledge (tree definitions and attributes)

1, the tree (non-linear data structures) used in some of the efficiency of the algorithm will be (based on the list and the list of the array) faster than the linear data structure, widely used file system directory structure, graphical user interface, MySQL database indexing, websites, routing agreements and other computer systems

2, a series of tree T is defined as a storage element is limited set of nodes, the nodes having a parent-children relationship satisfying properties: First, if the tree T is not empty, then it must have a special node called root node r, and the node has no parent; two, each non-root node has a unique v w parent node, each node having a parent node w is a child node of w

3, a v node without children is called an external node or a leaf node, a one or more child nodes called internal node v

4, the edge of the tree: a pair of nodes having parent-child relationship (u, v); Path Tree: a series of nodes of any two consecutive nodes having parent-child relationship

5, the ancestors of the node P: from the root node to all nodes on the path via the node P; descendants of the node P: P node in the subtree rooted at any node in the section are descendants of node P

6, ordered tree: If the child node of the tree each node has a specific order, called ordered tree. Ordered tree: binary, Huffman tree (encoding information), B tree (a kind of read and write operations to optimize the self-balancing binary search tree)

7, there are two kinds of lists and trees underlying storage array manner. Array storage memory access speed, the insert and delete node operation time than the complex list. It is more practical to store the tree chains

8, the depth of the tree of the node P T: the number of ancestors of node P (not including P itself) recursive definition: if P is a root node, depth P is 0; otherwise, the depth P 1 is the parent node plus the depth  

9, T in the height of the tree node P: If P is a leaf node, the height of P is 0; otherwise, the depth P is its child nodes maximum height plus one. T height of the tree is the root node of height! Height = "number of sides" on route nodes on the path = -1

 10, the node degree: contains the number of nodes of the subtree of this node is called; of the tree: the maximum degree of the nodes of the tree is called

def _height1(self):     # works but O(N^2)worst-case time
    """return the height of the tree"""
    return max(self.depth(p) for p in self.positions() if self.is_leaf(P))
 
def _height2(self,p):   # time is linear in size of subtree
    """return the height of the subtree rooted at Position p"""
     if self.is_leaf(P):
          return 0
     else:
    return 1+ max(self.height2(c) for c in self.children(p))

Third, the tree abstract data type

Tree abstract base class (internal details not described in full, does not implement the necessary behavior)

A, Tree abstract base class, BinaryTree Tree class inherits the abstract base class, holding abstract

1, p.element (): returns the element stored in the position p

2, T.root (): returns the position of the root node of the tree T, if the root node is empty, return None

3, T.is_root (P): determines whether or not the position P T is the root of the tree, and if so, returns True

4, T.parent (P): return position for the location of the parent node P, if P is the position of the root node, return None

5, T.num_children (P): Returns the number position for the child node P

6, T.children (P): generating an iterative position for children of the node P

7, T.is_leaf (P): P If the location does not have any children, returns True

8, len (T): Returns the element tree T contains the number

9, T.is_empty (): If the node does not contain any tree T, Return True

10, T.positions (): All locations spanning the iteration of T

11, (T) iter: iterate over all the elements of the spanning tree T stored

12, T.left (p): Returns the left child of p position, if p left no children, return None

13, T.right (p): Returns the right child position p, p if there is no right child, return None

14, T.sibling (p): p sibling node returns the location, if no sibling node p, return None

15, T.add_root (e): create a new root node, the memory elements E, and returns the position of the root node. If the tree is not empty, throw an error

16, T.add_left (p, e): Creates a new node, storage element e, and the link to the left child node position P. If the position P of the left child is not empty, throw an error

17, T.add_right (p, e): Creates a new node, storage element e, and the link to the right child node position P. If the position P of the right child is not empty, throw an error

18, T.replace (p, e): replace elements with element position p e, the element previously stored return

19, T.delete (p): p node removal position, and with his own children an alternative, if so, returns the element stored in the position p; if p has two children, throw an error

20, T.attach (p, T1, T2): the tree T1, T2 respectively linked to left and right subtree T P leaf nodes, and the tree T1, T2 is reset to empty tree; if p is not a leaf node, throwing an error

Fourth, the binary tree (Binary Tree)

First, the basics

1, is an ordered binary tree having the desired properties: First, each node has at most two children nodes; two, each child node is designated as the left child or right child; three children of each node, in the sequence the left and right child first child

2, a full binary tree: all leaf nodes of the same in the bottom (unprimed nodes are the internal node), a depth K (> = - . 1 ) and has 2 ^ (k + 1) - 1 nodes ( k = -1 indicates an empty tree)

3, complete binary tree: leaf node can only appear in the bottom two , and the bottom of the leaf nodes are at times underlying leaf nodes on the left side . In addition to the last leaf node of the parent node, if each node has zero or two child nodes.

4, the balanced binary tree: the absolute value of the difference between the height of the empty tree or a subtree left and right does not exceed 1, and the left and right sub-trees are a balanced binary tree

5, binary search tree (sort binary tree)

6, the method used to achieve a balanced binary tree has AVL, splay trees, red-black tree, scapegoat tree, like Treap

7, a binary tree properties: non-empty nodes of binary tree T n, external nodes n- E , the internal nodes n- the I , the height H (H ≦ n ≦ 2 + H +. 1 -1), log (n-+. 1) . 1-n--1≤h≤ ; complete binary tree: log (n-+. 1) -1≤h≤ (. 1-n-) / 2

8, binary tree traversal: traverse the level (breadth traversal); depth traversal: preorder (root >> >> left subtree right subtree), preorder (root >> >> left subtree right subtree) after preorder traversal (left subtree right subtree >> >> root)

Second, the binary tree based Storage Structure binary abstract base class implementation and increasing support element method and traversal methods: add (), breadth_travel (), preOrder (), inOrder (), postOrder ()

1, the definition of a binary tree node classes: class Node. The following is a singly linked list, a doubly linked list increase self.parent = None, a reference point to a parent node, if the node is the root node, the reference point None

class Node(object):
    def __init__(self, item):
        self.elem = item
        self.lchild = None
        self.rchild = None

2, the binary tree is defined according to the method of adding elements complete binary tree: Tree.add ()

class LinkedBinaryTree(object):
    def __init__(self):
        self.root = None

    def add(self, item):
        node = Node(item)
        if self.root is None:
            self.root = node
            return
        # Use queue FIFO, iterative query
        queue = [self.root]
        while queue:
            cur_node = queue.pop(0)
            if cur_node.lchild is None:
                cur_node.lchild = node
                return
            else:
                queue.append(cur_node.lchild)
            if cur_node.rchild is None:
                cur_node.rchild = node
                return
            else:
                queue.append(cur_node.rchild)

3, the definition of a binary tree hierarchy traversal (breadth-first traversal) method:. Tree breadth_travel ()

3.1, breadth-first traversal of the running time is O (n)

    def breadth_travel(self):
        if self.root is None:
            return
        queue=[self.root]
        while queue:
            cur_node=queue.pop(0)
            print(cur_node.elem, end=' ')
            if cur_node.lchild is not None:
                queue.append(cur_node.lchild)
            if cur_node.rchild is not None:
                queue.append(cur_node.rchild)

4, deep traversals: preorder preOrder (), after the sequence postorder traversal (), preorder inOrder ()

4.1, preorder and postorder overall run time is O (n), n is the number of positions in the tree

4.2, preorder traversal algorithm is directed to a binary tree, there are several important applications such as: arithmetic expression represented by (a parameter indicating a leaf node, internal nodes represent operators), inorder traversal algorithm ordered sequence of elements stored in the binary tree

    def preOrder(self, node):
        "" "Preorder" ""
        if node is None:
            return
        print(node.elem, end=' ')
        self.preOrder(node.lchild)
        self.preOrder(node.rchild)

    def inOrder(self, node):
        "" "Preorder" ""
        if node is None:
            return
        self.inOrder(node.lchild)
        print(node.elem, end=' ')
        self.inOrder(node.rchild)

    def postOrder(self, node):
        "" "Postorder" ""
        if node is None:
            return
        self.postOrder(node.lchild)
        self.postOrder(node.rchild)
        print(node.elem, end=' ')

5, test code

if __name__ == '__main__':
    node = Tree()
    node.add(1)
    node.add(2)
    node.add(3)
    node.add(4)
    node.add(5)
    node.add(6)
    node.add(7)
    node.breadth_travel()
    print('')
    node.preOrder(node.root)
    print(' ')
    node.inOrder(node.root)
    print('')
    node.postOrder(node.root)
    print('')

6, output

Third, based on an array of binary representation

1, T is the position numbering will be an array of binary tree representation.

2, T for each position p of the numbers f (p): If p is the root node, then f (p) = 0; q if p is a position left child, if f (p) = 2f (q) +1; If p is the right child of the position q, then f (p) = 2f (q) +2

3, greatly dependent on the shape of the tree based on the use of an array of spatial representation, array A = desired length. 1 + F N M . F M is the maximum value of f (p) in. A plurality of arrays may have empty cells, the existing node does not point T

4, the worst space requirement = 2 N n- -1, and tree update operation (deletion, addition, etc.) time complexity is O (n)

5, based on an array of binary representation

Fifth, the binary search tree

First, the basics

1, an important use is as a tree data structure search tree . Search elements tree structure effective to achieve an orderly map! (M [k], M [ k] = v, del M [k])

2, binary search tree: each storage node p is a key-value pair (k, v) of the binary tree T, and when satisfying bond position of the structural characteristics : First, the key is stored in the left subtree of p less than K; Second, the key is stored in the right subtree of p greater than k

Second, the binary search tree traversal M [k]

1、存储有序的序列的二叉搜索树中进行中序遍历算法:先左子树的递归地进行中序遍历会在孩子树上以递增的顺序产生键的迭代,然后根节点的访问,最后是右子树的递归进行中序遍历会在孩子树上以递增的顺序产生键的迭代。中序遍历可以在线性时间内被执行,对二叉搜索树进行中序遍历时,可以在线性时间内产生一个映射中所有键的有序迭代

2、二叉搜索树实现更细粒度的遍历,直接定位到指定元素节点:frist():返回包含最小键的节点,如果树为空,则返回None;last():返回包含最大键的节点,如果树为空,返回None;before(p)p的前驱节点:返回比节点p的键小的所有节点中键最大的节点,如果p是第一个节点,返回None(中序遍历在p之前最后一个被访问的节点--p的左子树中最右节点,如果没有左子树,p在父节点的右子树,则是p的父节点);after(p)p的后继节点:返回比节点p的键大的所有节点中键最小的节点,,如果p是最后一个节点,返回None(中序遍历在p之后第一个被访问的节点--p的右子树中最左节点,如果没有右子树,p在父节点的左子树,则是p的父节点)

3、二叉搜索算法:TreeSearch在路径上各个节点被调用,每个调用执行恒定数量的基本操作O(1)。节点的数目被设定为h+1(h+1次调用),h为T的高度,所以总的搜索时间是O(h)

6、非空二叉树T:log(n+1)-1≤h≤ n-1;完全二叉树:log(n+1)-1≤h≤(n-1)/2n为T的节点总数、h为高度,各种策略,是得搜索树T的高度上限是logn!

def TreeSearch(self, T, p, k):
    if k == p.key():
        return p
    elif k < p.key() and T.left(p) is not None:
        return self.TreeSearch(T, T.left(p), k)
    elif k > p.key() and T.right(p) is not None:
        return self.TreeSearch(T, T.right(p), k)
    # unsuccessful search
    return p 

三、二叉搜索树的插入和删除M[k]=v、del M[k]

1、M[k]=v:TreeSearch()遍历树T。如果存在k,则重新给节点赋值为v;如果不存在,即遍历最后子树为None,则在该位置插入新的节点(kv

def TreeInsert(T, k, v):
    p=TreeSearch(T, T.root(), k)
    if k == p.key() then
        Set p's value to v 
    elif k < p.key() then
        add node with item(k,v) as left child of p
    else:
        add node with item(k,v) as right child of p

2、del M[k]:情况一、存储k的节点p只有一个孩子:删除节点p,并用孩子节点代替p;

-----------------情况二、存储k的节点p有两个孩子:一、r=befor(p),二、r替代p,三、由于r=befor(p)而且p有两个孩子,所以r是p左子树中最右节点,即没有右子树,按照情况一删除-----------------树中原来r位置的节点

四、二叉搜索树性能

五、python代码

# node in-order traversal(LDR)
def traversal(node):
    if not node:
        return
    traversal(node.lchild)
    print(node.value,end=' ')
    traversal(node.rchild)

# insert node
def insert(root, value):
    if not root:
        return Node(value)
    if value < root.value:
        root.lchild = insert(root.lchild, value)
    elif value > root.value:
        root.rchild = insert(root.rchild, value)
    return root

# delete node
def delete(root, value):
    if not root:
        return None
    if value < root.value:
        root.lchild = delete(root.lchild, value)
    elif value > root.value:
        root.rchild = delete(root.rchild, value)
    else:
        if root.lchild and root.rchild:  # degree of the node is 2
            target = root.lchild  # find the maximum node of the left subtree
            while target.rchild:
                target = target.rchild
            root = delete(root, target.value)
            root.value = target.value
        else:  # degree of the node is [0|1]
            root = root.lchild if root.lchild else root.rchild
    return root

 六、平衡搜索树

1、保证最坏情况下,搜索、插入和删除的操作的时间复杂度是O(logn)的搜索树算法:AVL树、伸展树、红黑树

2、平衡搜索树:某些操作系列会生成高度与n成比例的不平衡树,这种树的时间复杂度是O(n)。平衡搜索树是通过旋转操作调整不平衡树高度,使树避免非常不平衡的数结构。

3、平衡二叉搜索树的主要操作:旋转。第一步:修改位置两个位置父子关系;第二步:利用被旋转的两个位置之间的键连接子树节点。旋转之后二叉树键的结构特性保持不变!

4、单个旋转修改位置p的父子关系;双旋转是位置p在3个关联的键的中键时,第一次旋转到p的父节点上,第二次旋转到p祖父节点上;时间复杂度均为O(1)

5、trinode重组:在一棵树内部,将一个或多个旋转合并来提供更广泛的平衡的复合操作>>>4种可能,2种单旋转+2种双旋转;时间复杂度为O(1)

6、h+1≤n≤2h+1-1、h<2log(n(h))+2、

7、平衡操作的钩子,

8、平衡搜索树的“旋转”代码

def _relink(self, parent, child, make_left_child):
    """relink parent node with child node(allow child to be none"""
    if make_left_child:  # make it a left child
        parent._left = child
    else:
        parent._right = child  # make it a _right child
    if child is not None:  # make child to parent
        child._parent = parent


def _rotate(self, p):
    """rotate position p above its parent"""
    x = p.__node
    y = x.__parent
    z = y.__parent
    if z is None:
        x.__parent = None  # X becomes root
    else:
        self._relink(z, x, y == z.__left)  # x becomes a direct child of z
    # now rotate x and y,including transfer of middle subtree
    if x == y.__left:
        self._relink(y, x.__left, True)  # x.__left becomes left child of y
        self._relink(x, y, False)  # y becomes right child of x
    else:
        self._relink(y, x.__left, False)  # x.__left becomes right child of y
        self._relink(x, y, True)  # y becomes left child of x


def _restructure(self, x):
    """perform trinode restructure of position x with parent/grandparent"""
    y = self.parent(x)
    z = self.parent(y)
    if (x == self.right(y)) == (y == self.right(z)):  # matching alignments
        self._rotate(y)  # single rotation (of y)
        return y  # y is new subtree root
    else:
        self._rotate(x)     # opposite alignments
        self._rotate(x)     # double rotation(of x)
        return x     # x is new subtree root  

 

 

Guess you like

Origin www.cnblogs.com/yinminbo/p/11887189.html
Recommended