【数据结构与算法】task5 二叉树&堆

二叉树

定义

二叉查找树(Binary Search Tree),又称为二叉搜索树、二叉排序树。其或者是一棵空树;或者是具有以下性质的二叉树:

  • 若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值
  • 若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值
  • 左、右子树也分别为二叉排序树

树中节点的定义如下:

class Node:
    def __init__(self, data):
        self.data = data
        self.lchild = None
        self.rchild = None

实现一个二叉查找树,并且支持插入、删除、查找操作

参考:https://blog.csdn.net/u010089444/article/details/70854510

https://www.cnblogs.com/lilip/p/9937697.html

查找与插入

当二叉查找树不为空时:

首先将给定值与根结点的关键字比较,若相等,则查找成功
若小于根结点的关键字值,递归查左子树
若大于根结点的关键字值,递归查右子树
若子树为空,查找不成功
二叉排序树是一种动态树表。其特点是:树的结构通常不是一次生成的,而是在查找过程中,当树中不存在关键字等于给定值的结点时再进行插入。新插入的结点一定是一个新添加的叶子结点,并且是查找不成功时查找路径上访问的最后一个结点的左孩子或右孩子结点。如下图所示: 

     # 搜索
    def search(self, node, parent, data):
        if node is None:
            return False, node, parent
        if node.data == data:
            return True, node, parent
        if node.data > data:
            return self.search(node.lchild, node, data)
        else:
            return self.search(node.rchild, node, data)

    # 插入
    def insert(self, data):
        flag, n, p = self.search(self.root, self.root, data)
        if not flag:
            new_node = Node(data)
            if data > p.data:
                p.rchild = new_node
            else:
                p.lchild = new_node

删除

    # 删除
    def delete(self, root, data):
        flag, n, p = self.search(root, root, data)
        if flag is False:
            print "无该关键字,删除失败"
        else:
            if n.lchild is None:
                if n == p.lchild:
                    p.lchild = n.rchild
                else:
                    p.rchild = n.rchild
                del n
            elif n.rchild is None:
                if n == p.lchild:
                    p.lchild = n.lchild
                else:
                    p.rchild = n.lchild
                del n
            else:  # 左右子树均不为空
                pre = n.rchild
                if pre.lchild is None:
                    n.data = pre.data
                    n.rchild = pre.rchild
                    del pre
                else:
                    next = pre.lchild
                    while next.lchild is not None:
                        pre = next
                        next = next.lchild
                    n.data = next.data
                    pre.lchild = next.rchild
                    del next

实现查找二叉查找树中某个节点的后继、前驱节点

参考:https://www.cnblogs.com/icekx/p/9131618.html

https://blog.csdn.net/weixin_41712499/article/details/85860972

https://blog.csdn.net/zxzxzx0119/article/details/81097546

若节点类型没有parent属性,采用中序遍历方式获取后继节点:

def getSuccessorNode(head, node):
    if (not node) or (not head):
        return None
    stack = []
    flag = False
    while head or len(stack) > 0:
        if head:
            stack.append(head)
            head = head.left
        else:
            head = stack.pop()
            if flag:
                return head
            if head == node:            # 若找到当前节点,则下一个弹出的节点即为后继节点
                flag = True
            head = head.right
    return None

若节点存在parent属性即:

class TreeNode:
    def __init__(self, x=0):
        self.val = x
        self.parent = None
        self.left = None
        self.right = None


def getSuccessorNode(node):
    if not node :
        return None
    if node.right:               # 如果当前节点有右子树,则返回右子树的最左边节点
        node = node.right
        while node.left:
            node = node.left
        return node
    else:                        # 没有右子树   则向上找寻父节点,直到为父节点的左子树,返回父节点,否则返回空
        par = node.parent
        while not par and par.left != node:
            node = par
            par = par.parent
        return par

实现二叉树前、中、后序以及按层遍历

参考:https://blog.csdn.net/qq_34364995/article/details/80787116

https://www.cnblogs.com/bjwu/p/9284534.html

# -*- coding:utf-8 -*-
'''
用Python实现树,并遍历。
'''


class Node():
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None


def depth(root):
        if root is None:
            return 0
        else:
            return 1 + max(depth(root.left), depth(root.right))

    #前序遍历
def pre_order(root):
        if root is None:
             return
        else:
            print(root.val)
            pre_order(root.left)
            pre_order(root.right)

    #中序遍历
def mid_order(root):
        if root is None:
            return
        else:
            mid_order(root.left)
            print(root.val)
            mid_order(root.right)


    #后序遍历
def post_order(root):
        if root is None:
            return
        else:
            post_order(root.left)
            post_order(root.right)
            print(root.val)

#层次遍历
def level_order(root):
    if root is None:
        return
    q = []
    q.append(root)
    while q:
        current = q.pop(0)
        print(current.val)
        if current.left != None:
            q.append(current.left)
        if current.right != None:
            q.append(current.right)

#按层次打印
def level_print(root):
    if root is None:
        return []
    p = [root]
    results = []
    current_level_num = 1
    next_level_num = 0
    d = []
    while p:
        current = p.pop(0)
        d.append(current.val)
        current_level_num -= 1
        if current.left:
                p.append(current.left)
                next_level_num += 1
        if current.right:
                p.append(current.right)
                next_level_num += 1
        if current_level_num == 0:
            current_level_num = next_level_num
            next_level_num = 0
            results.append(d)
            d = []
    return results[::-1]



if __name__ == '__main__':
    a = Node(3)
    b = Node(9)
    c = Node(20)
    d = Node('null')
    e = Node('null')
    f = Node(15)
    g = Node(7)
    a.left = b
    a.right = c
    b.left = d
    b.right = e
    c.left = f
    c.right = g
    print('深度:%d' % depth(a))
    print("前序遍历:")
    print(pre_order(a))
    print('中序遍历:')
    print(mid_order(a))
    print('后序遍历:')
    print(post_order(a))
    level_order(a)
    print(level_print(a))

leetcode-98 验证二叉搜索树

题目:https://leetcode-cn.com/problems/validate-binary-search-tree/

参考:https://blog.csdn.net/ma412410029/article/details/80733905

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

class Solution(object):
    def isValidBST(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        def inorderTraversal(root): 
            if root == None:
                return []
            res = []
            res += inorderTraversal(root.left)
            res.append(root.val)
            res += inorderTraversal(root.right)
            return res
 
        res = inorderTraversal(root)
        if res != sorted(list(set(res))): return False
        return True

leetcode-102 二叉树的层次遍历

https://leetcode-cn.com/problems/binary-tree-level-order-traversal/

参考:https://blog.csdn.net/weixin_40314737/article/details/80942856

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

class Solution(object):
    def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        queue = [root]
        res = []
        if not root:
            return []
        while queue:
            templist = []
            templen =len(queue)
            for i in range(templen):                
                temp = queue.pop(0)
                templist.append(temp.val)
                if temp.left:
                    queue.append(temp.left)
                if temp.right:
                    queue.append(temp.right)
            res.append(templist)
        return res

leetcode-107 二叉树的层次遍历 II

https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii/

参考:https://blog.csdn.net/qq_34364995/article/details/80427199

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

class Solution(object):
    def levelOrderBottom(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        if not root:
            return []
        queue = [root]
        res = []
        while queue:
            templist = []
            length = len(queue)
            for i in range(length):
                temp = queue.pop(0)
                templist.append(temp.val)
                if temp.left:
                    queue.append(temp.left)
                if temp.right:
                    queue.append(temp.right)
            res.append(templist)
        return res[::-1]

实现一个小顶堆、大顶堆、优先级队列

参考:https://www.coder4.com/archives/3844

小顶堆

import heapq
import random

class TopkHeap(object):
    def __init__(self, k):
        self.k = k
        self.data = []

    def Push(self, elem):
        if len(self.data) < self.k:
            heapq.heappush(self.data, elem)
        else:
            topk_small = self.data[0]
            if elem > topk_small:
                heapq.heapreplace(self.data, elem)

    def TopK(self):
        return [x for x in reversed([heapq.heappop(self.data) for x in xrange(len(self.data))])]

if __name__ == "__main__":
    print "Hello"
    list_rand = random.sample(xrange(1000000), 100)
    th = TopkHeap(3)
    for i in list_rand:
        th.Push(i)
    print th.TopK()
    print sorted(list_rand, reverse=True)[0:3]

大顶堆

class BtmkHeap(object):
    def __init__(self, k):
        self.k = k
        self.data = []

    def Push(self, elem):
        # Reverse elem to convert to max-heap
        elem = -elem
        # Using heap algorighem
        if len(self.data) < self.k:
            heapq.heappush(self.data, elem)
        else:
            topk_small = self.data[0]
            if elem > topk_small:
                heapq.heapreplace(self.data, elem)

    def BtmK(self):
        return sorted([-x for x in self.data])

优先级队列

参考:https://blog.csdn.net/j086924/article/details/82736301

import heapq
 
class PriorityQueue:
    def __init__(self):
        self._queue = []
        self._index = 0
 
    def push(self, item, priority):
        heapq.heappush(self._queue, (-priority, self._index, item))
        self._index += 1
 
    def pop(self):
        return heapq.heappop(self._queue)[-1]
 
class Item:
    def __init__(self, name):
        self.name = name
 
    def __repr__(self):
        return 'Item({!r})'.format(self.name)
 
if __name__ == "__main__":
    q = PriorityQueue()
    q.push(Item('python'), 1)
    q.push(Item('java'), 5)
    q.push(Item('swift'), 4)
    q.push(Item('c++'), 1)
    for i in range(4):
        print(q.pop())

实现堆排序

参考:https://www.jianshu.com/p/d174f1862601

from collections import deque

def swap_param(L, i, j):
    L[i], L[j] = L[j], L[i]
    return L

def heap_adjust(L, start, end):
    temp = L[start]

    i = start
    j = 2 * i

    while j <= end:
        if (j < end) and (L[j] < L[j + 1]):
            j += 1
        if temp < L[j]:
            L[i] = L[j]
            i = j
            j = 2 * i
        else:
            break
    L[i] = temp

def heap_sort(L):
    L_length = len(L) - 1

    first_sort_count = L_length / 2
    for i in range(first_sort_count):
        heap_adjust(L, first_sort_count - i, L_length)

    for i in range(L_length - 1):
        L = swap_param(L, 1, L_length - i)
        heap_adjust(L, 1, L_length - i - 1)

    return [L[i] for i in range(1, len(L))]

def main():
    L = deque([50, 16, 30, 10, 60,  90,  2, 80, 70])
    L.appendleft(0)
    print heap_sort(L)

if __name__ == '__main__':
    main()

利用优先级队列合并 K 个有序数组

参考:https://blog.csdn.net/u012328476/article/details/52522900

https://blog.csdn.net/qiuye2014/article/details/86707126

求一组动态数据集合的最大 Top K

参考:https://github.com/wangzheng0822/algo/blob/master/python/28_binary_heap/top_k.py

import random
from heap import MinHeap


def top_k(nums, k):
    """
    返回数组的前k大元素
    :param nums:
    :param k:
    :return:
    """
    if len(nums) <= k:
        return nums

    min_h = MinHeap(nums[:k], k)
    for i in range(k, len(nums)):
        tmp = min_h.get_top()
        if nums[i] > tmp:
            min_h.remove_top()
            min_h.insert(nums[i])

    return min_h.get_data()

if __name__ == '__main__':
    nums = []
    k = 3

    for i in range(20):
        nums.append(random.randint(1, 100))

    print('--- nums ---')
    print(nums)

    print('--- top {} ---'.format(k))
    print(top_k(nums, k))

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值