Python data structure and algorithm tree

Definition of tree

In computer science, tree is a kind of abstract data type or a data structure to realize this kind of abstract data type, which is used to simulate the data set with tree structure. It is a set of n (n > 0) finite nodes with hierarchical relationship. It's called "tree" because it looks like an upside down tree, that is, it's root up and leaf down. It has the following characteristics

  • Each node has zero or more child nodes;
  • A node without a parent node is called a root node;
  • Each non root node has only one parent node;
  • In addition to the root node, each sub node can be divided into multiple disjoint sub trees;

Tree is implemented by list

Idea: for a list:['q ', [], []], it represents a tree (subtree),' Q 'is the root node, [], [] are left and right child nodes respectively. Therefore, a tree with a left node of 'a' can be written as ['q',['a', [], []], []]. In this case, the root node is my_tree[0], left node is my_tree[1], the right node is my_tree[2].

Example: my_tree = ['a', ['b', ['d',[],[]], ['e',[],[]] ], ['c',['f',[],[]], []] ]


def binary_tree(root):
    return [root, [], []]


def insert_left(root, new_branch):
    t = root.pop(1)

    if len(t) > 0:
        root.insert(1, [new_branch, t, []])
    else:
        root.insert(1, [new_branch, [], []])


def insert_right(root, new_branch):
    t = root.pop(2)

    if len(t) > 0:
        root.insert(2, [new_branch, [], t])
    else:
        root.insert(2, [new_branch, [], []])


def get_root_value(root):
    return root[0]


def set_root_value(root, value):
    root[0] = value


def get_left_value(root):
    return root[1]


def get_right_value(root):
    return root[2]

Chain structure implementation tree


class LinkedTree:
    def __init__(self, obj):
        self.__key = obj
        self.__left_child = None
        self.__right_child = None

    def insert_left_child(self, new_node):
        if self.__left_child == None:
            self.__left_child = LinkedTree(new_node)
        else:
            t = LinkedTree(new_node)
            t.__left_child = self.__left_child
            self.__left_child = t

    def insert_right_child(self, new_node):
        if self.__right_child == None:
            self.__right_child = LinkedTree(new_node)
        else:
            t = LinkedTree(new_node)
            t.__right_child = self.__right_child
            self.__right_child = t

    def get_root_value(self):
        return self.__key

    def set_root_value(self, value):
        self.__key = value

    def get_left_child(self):
        return self.__left_child

    def get_right_child(self):
        return self.__right_child

    def preorder(self):
        print(self.__key)

        if self.__left_child:
            self.__left_child.preorder()

        if self.__right_child:
            self.__right_child.preorder()

    def middleorder(self):
        if self.__left_child:
            self.__left_child.middleorder()

        print(self.__key)

        if self.__right_child:
            self.__right_child.middleorder()

    def postorder(self):
        if self.__left_child:
            self.__left_child.postorder()

        if self.__right_child:
            self.__right_child.postorder()

        print(self.__key)

Application of tree

Building an expression tree

The analytic expression can be expressed as a tree, for example: ((7 + 3) * 5 − 2)) can be expressed as

The formation of the parse tree can be defined as the following four rules:

  1. If (, which means there is a new expression, create a new subtree (add a new sub node, and then create the left sub node of the new node, and move the processing target to the left sub node)

  2. If [+, -, *, /] operators are encountered, place this operator on the current node, create a right child node, and move the processing target to this right child node

  3. If a number is encountered, place the number in the current node and return the processing target to the parent node

  4. If encountered), return the processing target to the parent node.


def build_exp_tree(fpexp):
    fplist = fpexp.split()
    fp_stack = Stack()
    etree = LinkedTree('')
    fp_stack.push(etree)
    current_tree = etree

    for i in fplist:
        if i == "(":
            current_tree.insert_left_child('')
            fp_stack.push(current_tree)
            current_tree = current_tree.get_left_child()
        elif i not in ['+', '-', '*', '/', ')']:
            current_tree.set_root_value(int(i))
            parent = fp_stack.pop()
            current_tree = parent
        elif i in ['+', '-', '*', '/']:
            current_tree.set_root_value(i)
            current_tree.insert_right_child('')
            fp_stack.push(current_tree)
            current_tree = current_tree.get_right_child()
        elif i == ')':
            current_tree = fp_stack.pop()
        else:
            raise ValueError()

    return etree

Because the binary tree class constructed between cannot access its parent node, a new stack should be built here to store the current parent node.

In the case of (and operators, both operations need to move the current operation node to the left and right children, so these two operations need to stack the parent node.

Solving expressions

import operator

def evaluate(expression_tree):
    opers = {
        '+': operator.add,
        '-': operator.sub,
        '*': operator.mul,
        '/': operator.truediv
    }

    res1 = res2 = None

    if expression_tree:
        res1 = evaluate(expression_tree.get_left_child())
        res2 = evaluate(expression_tree.get_right_child())

        if res1 and res2:
            return opers[expression_tree.get_root_value](res1, res2)
        else:
            return expression_tree.get_root_value()


Tags: Programming

Posted on Mon, 08 Jun 2020 22:56:52 -0400 by johnc71