python implemented data structure (V)

1. Binary Tree

1.1 implement a binary search tree, and supports insert, delete, search operations

class Node:
    def __init__(self, value, lchild=None, rchild=None):
        self.data = value
        self.lchild = lchild
        self.rchild = rchild
        
class BSTree:
    def __init__(self, value):
        self.root = Node(value)
    
    def insert(self, value):
        '''
        插入值为value的结点
        二叉排序树插入的结点一定为叶子结点
        '''
        node = Node(value)
        p = self.root; pre = None
        while p:
            pre = p
            if p.data > value:
                p = p.lchild
            elif p.data < value:
                p = p.rchild
            else:
                break
        if p == None:       # 当该结点不存在于当前的二叉排序树中,插入结点
            if pre.data > value:
                pre.lchild = node
            else:
                pre.rchild = node
        
    def find(self, value):
        p = self.root
        while p:
            if p.data > value:
                p = p.lchild
            elif p.data < value:
                p = p.rchild
            else:
                print('已找到该结点')
                break
        if p == None:
            raise Exception('value error: %d do not exist in BSTree ' % value)
        return p
    
    def findParent(self, target):
        '''
        查找二叉排序树中目标结点的父结点
        :param bstree: 二叉排序树的根结点
        :param target: 目标结点
        '''
        p = self.root; pre = None
        while p:
            if target.data < p.data:
                pre = p
                p = p.lchild
            elif target.data > p.data:
                pre = p
                p = p.rchild
            else:
                if p is target:
                    break
                else:
                    pre = p
                    # 目标结点为中序序列的后一个相邻结点,故在右子树中
                    p = p.rchild      
        if p == None:
            raise Exception('value error: %d do not exist in bstree' % value)
        else:
            return pre
    
    def remove(self, node, value):
        '''
        删除二叉排序树中值为value的结点
        目标结点p的位置可能有以下三种情况:
        1) p为叶子结点:直接删除即可
        2) p有左子树或右子树其中之一:删除p,p的父结点连接到p的子树
        3) p同时有左右子树:选中序序列中与p相邻的两个结点之一覆盖p结点,
        再依据1)或2)删除该结点
        '''
        p = node; pre = None
        while p:
            if p.data > value:
                pre = p
                p = p.lchild
            elif p.data < value:
                pre = p
                p = p.rchild
            else:           # 找到待删结点之后进行的操作
                if p.lchild and p.rchild:       # 情况3)要删除的结点
                    temp = p.rchild
                    while temp.lchild:
                        temp = temp.lchild
                    p.data = temp.data          # 找到中序序列后一个结点temp覆盖待删结点p
                    
                    '''
                    以下在二叉排序树中找到temp结点并删除(由于此时有两个相同值的结点,
                    故在查找时还需用地址进行比较(findParent(target)中))
                    temp结点只有两种可能:
                    1)叶子结点
                    2)只有右子树
                    '''
                    if temp.lchild == None and temp.rchild == None:        # 情况1)待删结点为叶子结点
                        self._removeLeaf(temp)
                        break
                    else:                                                   # 情况2)待删结点只有右子树
                        parentTemp = self.findParent(temp)
                        self._changeChild(parentTemp, temp, temp.rchild)                 
                elif p.lchild:                  # 情况2)待删结点只有左子树
                    self._changeChild(pre, p, p.lchild)
                    break
                elif p.rchild:                  # 情况2)待删结点只有右子树
                    self._changeChild(pre, p, p.rchild)
                    break
                else:                           # 情况1)待删结点为叶子结点
                    self._removeLeaf(p)
                    break

    def _changeChild(self, parent, preChild, afterChild):
        if parent.lchild == preChild:
            parent.lchild = afterChild
            print('remove success')
        else:
            parent.rchild = afterChild
            print('remove success')
    
    def _removeLeaf(self, leaf):
        parent = self.findParent(leaf)
        if parent == None:      # 待删结点为二叉排序树的唯一结点
                self.root = None
        else:
            if parent.lchild and parent.lchild.data == leaf.data:
                parent.lchild = None
            else:
                parent.rchild = None

1.2 The Find a binary search tree node successor, predecessor node

1.2.1 python achieve find a node in a binary search tree precursor node

def findParent(bstree, value):
    '''
    查找二叉排序树中值为value的结点的前驱结点
    :param bstree: 二叉排序树的根结点
     :param value: 目标结点的值
    '''
    p = bstree; pre = None
    while p:
        if value < p.data:
            pre = p
            p = p.lchild
        elif value > p.data:
            pre = p
            p = p.rchild
        else:
            break
    if p == None:
        raise Exception('value error: %d do not exist in bstree' % value)
    else:
        return pre.data

1.2.2 python implement a binary search to find a successor node tree node

def findPost(bstree, value):
    '''
    查找二叉排序树中值为value的结点的后继结点
    :param bstree: 二叉排序树的根结点
     :param value: 目标结点的值
    '''
    p = bstree
    while p:
        if value < p.data:
            p = p.lchild
        elif value > p.data:
            p = p.rchild
        else:
            break
    if p == None:
        raise Exception('value error: %d do not exist in bstree' % value)
    elif p.lchild and p.rchild:
        return p.lchild.data, p.rchild.data
    else:
        re = p.lchild if p.lchild else p.rchild
        return re.data

1.3 binary implemented before, during and after the sequence and traverse the layer

1.3.1 traversing Binary Tree

def preOrder(bt):
    if bt:
        print(bt.data)
        preOrder(bt.lchild)
        preOrder(bt.rchild)

Traversing Binary Tree 1.3.2

def inOrder(bt):
    # 中序遍历
    if bt:
        inOrder(bt.lchild)
        print(bt.data)
        inOrder(bt.rchild)

After traversing Binary Tree 1.3.3

def postOrder(bt):
    # 后序遍历
    if bt:
        postOrder(bt.lchild)
        postOrder(bt.rchild)
        print(bt.data)

1.3.4 binary tree traversal level

class Queue:
    # 定义一个循环队列
    def __init__(self, capacity=10):
        self.front = 0
        self.rear = 0
        self.data = [None] * capacity
        self.size = 0
        self.maxsize = capacity
        
    def enQueue(self, node):
        self.rear = (self.rear + 1) % self.maxsize
        self.data[self.rear] = node
        self.size += 1
        
    def deQueue(self): 
        self.front = (self.front + 1) % self.maxsize
        self.size -= 1
        return self.data[self.front]
    
def levelOrder(bt):
    queue = Queue()
    queue.enQueue(bt)
    while queue.size != 0:
        q = queue.deQueue()
        print(q.data,end=' ')
        if q.lchild:
            queue.enQueue(q.lchild)
        if q.rchild:
            queue.enQueue(q.rchild)

1.4 LeetCode related exercises

1.4.1 Invert Binary Tree (binary flip)

class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if root:
            root.left, root.right = root.right, root.left
            self.invertTree(root.left)
            self.invertTree(root.right)
        return root

1.4.2 Maximum Depth of Binary Tree (binary maximum depth)

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        if root == None:
            return 0
        else:
            leftdepth = self.maxDepth(root.left)
            rightdepth = self.maxDepth(root.right)
            depth = leftdepth if leftdepth > rightdepth else rightdepth
            return depth + 1

1.4.3 Validate Binary Search Tree (verified binary search tree)

The lower limit of the recursive traversal of each node, each node has its should be consistent: the
left subtree of nodes: less than than the negative infinity parent node
node right subtree: less than positive infinity greater than the parent node

import sys
from functools import lru_cache

class Solution:
    lru_cache(10**8)
    def isValidBST(self, root: TreeNode) -> bool:
        def helper(node, lower, upper):
            if node == None:
                return True
            
            if node.val > lower and node.val < upper:
                return helper(node.left, lower, node.val) and helper(node.right, node.val, upper)
            else:
                return False
        return helper(root, float('-inf'), float('inf'))

1.4.4 python achieve binary tree traversal levels (102, 107)

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        if root:
            res = []
            level = [root]
            while level:
                temp1 = []
                for _ in level:
                    temp1.append(_.val)
                res.append(temp1)
                temp2 = []
                for n in level:
                    if n.left:
                        temp2.append(n.left)
                    if n.right:
                        temp2.append(n.right)
                level = temp2
            return res
        else:
            return [] 
            

1.4.5 python achieve binary tree traversal level (107)

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def levelOrderBottom(self, root: TreeNode) -> List[List[int]]:
        if root:
            res = []
            level = [root]
            while level:
                temp1 = []
                for _ in level:
                    temp1.append(_.val)
                res.append(temp1)
                temp2 = []
                for n in level:
                    if n.left:
                        temp2.append(n.left)
                    if n.right:
                        temp2.append(n.right)
                level = temp2
            res.reverse()
            return res
        else:
            return [] 

2. heap

2.1 to achieve a small pile top, big top of the heap

# 小顶堆
def smallerAdjust(arr, low, high):
    # 向下调整arr数组low位置上的元素
    temp = arr[low]
    i = low; j = 2 * i
    while i < j and j < high:
        if arr[j] > arr[j+1]:
            j += 1
        if temp > arr[j]:
            arr[i] = arr[j]
            i = j; j = 2 * i
        else:
            break
    arr[i] = temp
    
def smallerHeap(arr):
    length = len(arr)
    for i in range(length//2 : -1 : -1):
        smallerAdjust(arr, i, length-1)
# 大顶堆
def biggerAdjust(arr, low, high):
    # 向下调整arr数组low位置上的元素
    temp = arr[low]
    i = low; j = 2 * i
    while i < j and j < high:
        if arr[j] < arr[j+1]:
            j += 1
        if temp < arr[j]:
            arr[i] = arr[j]
            i = j; j = 2 * i
        else:
            break
    arr[i] = temp

def biggerHeap(arr):
    length = len(arr)
    for i in range(length//2 : -1 : -1):
        biggerAdjust(arr, i, length-1)

2.2 implement heap sort

'''
堆可以看做是一棵完全二叉树,这里使用大顶堆,则该完全二叉树的根结点即为最大值。
堆排序的基本思想:
将初始序列按照顺序写出其完全二叉树形式,对所有的非叶子节点从下往上,从右往左依次做调整(要求以其为根结点的二叉树也是大顶堆),建堆完毕;
此时根结点为最大值,将其与最后一个结点交换,则最大值到达其最终位置,之后继续对二叉树剩下的结点做同样的调整(此时只有刚换上去的根结点需要调整)

'''
def adjust(arr, low, high):
    # 向下调整k位置上的结点
    i = low; j = 2*i;
    temp = arr[low]
    while i <= j and j < high:
        if arr[j] < arr[j+1]:         # 将左右结点中最大的结点当做arr[j]
            j += 1
        if arr[j] > temp:
            arr[i] = arr[j]
            i = j; j = 2*i            # 循环做对下一个根结点的调整
        else:
            break
    arr[i] = temp       # 存于最终位置
    
def heapSort(arr):
    length = len(arr)
    for i in range(length//2,-1,-1):    # 建堆
        adjust(arr, i ,length-1)
    for index in range(length-1, -1, -1):    # 将根结点与每一趟的最后一个结点交换,再调整
        arr[index], arr[0] = arr[0], arr[index]   # 该趟最大值已到最终位置
        adjust(arr, 0, index-1)                  # 新一轮的调整

2.3 seeking a set of dynamic data set maximum Top K

# 利用大顶堆结构求出数组中的top K个值

# 大顶堆
def biggerAdjust(arr, low, high):
    # 向下调整arr数组low位置上的元素
    temp = arr[low]
    i = low; j = 2 * i
    while i <= j and j < high:
        if arr[j] < arr[j+1]:
            j += 1
        if temp < arr[j]:
            arr[i] = arr[j]
            i = j; j = 2 * i
        else:
            break
    arr[i] = temp
        
def topK(arr, k):
    length = len(arr)
    for i in range(length//2,-1,-1):    # 初始堆
        biggerAdjust(arr, i, length-1)
    re, end = [], length-1
    for i in range(k):
        re.append(arr[0])
        arr[0] = arr[end]
        end -= 1
        biggerAdjust(arr, 0, end)
    return re

2.4 LeetCode related exercises

2.4.1 Path sum

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def hasPathSum(self, root: TreeNode, sum: int) -> bool:
        if not root:
            return False
        
        if sum == root.val and (not root.left and not root.right):
            return True
        
        else:
            return self.hasPathSum(root.left, sum-root.val) or \
            self.hasPathSum(root.right, sum-root.val)

Guess you like

Origin blog.csdn.net/shichensuyu/article/details/90439003