数据结构与算法:二叉树+堆

【二叉树】

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

class Node:

    def __init__(self, data):

        self.data = data

        self.lchild = None

        self.rchild = None

class BST:

    def __init__(self, node_list):

        self.root = Node(node_list[0])

        for data in node_list[1:]:

            self.insert(data)

    # 查找

    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 p

            elif n.rchild is None:

                if n == p.lchild:

                    p.lchild = n.lchild

                else:

                    p.rchild = n.lchild

                del p

            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 p

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

class Solution:
    def GetNext(self, pNode):
        # write code here
        dummy = pNode
        #找到根节点
        while dummy.next:
            dummy = dummy.next
        #中序遍历
        ls = self.inorderTraversal(dummy)
        #找pNode所在索引的下一个
        if ls.index(pNode) != (len(ls)-1):
            return ls[ls.index(pNode)+1]
        else:
            return None

    def GetBefore(self, pNode):
        # write code here
        dummy = pNode
        #找到根节点
        while dummy.next:
            dummy = dummy.next
        #中序遍历
        ls = self.inorderTraversal(dummy)
        #找pNode所在索引的下一个
        if ls.index(pNode) != 0:
            return ls[ls.index(pNode)-1]
        else:
            return None

    def inorderTraversal(self, root):
        if root==None:
            return []
        return self.inorderTraversal(root.left)+[root]+self.inorderTraversal(root.right)

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

class Solution:
    def preorderTraversal(self, root: TreeNode) -> List[int]:
        if root==None:
            return []
        return [root.val]+self.preorderTraversal(root.left)+self.preorderTraversal(root.right)

    def inorderTraversal(self, root: TreeNode) -> List[int]:
        if root==None:
            return []
        return self.inorderTraversal(root.left)+[root.val]+self.inorderTraversal(root.right)

    def postorderTraversal(self, root: TreeNode) -> List[int]:
        if root==None:
            return []
        return self.postorderTraversal(root.left)+self.postorderTraversal(root.right)+[root.val]
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []
        result = []
        queue = collections.deque()
        queue.append(root)
        while queue:
            level_size = len(queue)
            current_level = []
            for _ in range(level_size):
                node = queue.popleft()
                current_level.append(node.val)
                if node.left: queue.append(node.left)
                if node.right: queue.append(node.right)
            result.append(current_level)
        return result

  练习:

  1. 翻转二叉树 https://leetcode-cn.com/problems/invert-binary-tree/

  思路:递归

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

  2. 二叉树的最大深度 https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/

  思路:1. 深度优先搜索 2. 广度优先搜索

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        if root is None:
            return 0
        ‘‘‘
        #深度优先搜索+分治
        return max(self.maxDepth(root.left), self.maxDepth(root.right))+1
        ‘‘‘
        ‘‘‘
        #深度优先搜索+栈
        self.ans = 0
        self._dfs(root, 0)
        return self.ans

    def _dfs(self, node, level):
        if not node:
            return
        if self.ans < level + 1:
            self.ans = level + 1
        self._dfs(node.left, level + 1)
        self._dfs(node.right, level + 1)
        ‘‘‘
        #广度优先搜索+双端队列deque
        queue = collections.deque()
        queue.append(root)
        ans = 0
        while queue:
            ans += 1
            for _ in range(len(queue)):
                node = queue.popleft()
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
        return ans

  3. 验证二叉查找树 [作为可选] https://leetcode-cn.com/problems/validate-binary-search-tree/

  思路:递归

class Solution:
    def isValidBST(self, root: TreeNode) -> bool:
        #max(leftnode)<root
        #min(rightnode)>root
        return self.valid(root, float(‘-inf‘), float(‘inf‘))

    def valid(self, root, min, max):
        if not root:
            return True
        if root.val >= max or root.val <= min:
            return False
        return self.valid(root.left, min, root.val) and self.valid(root.right, root.val, max)

【堆】

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

class ZHeap:
    def __init__(self, item=[]):
        # 初始化。item为数组
        self.items = item
        self.heapsize = len(self.items)

    def LEFT(self, i):
        return 2 * i + 1

    def RIGHT(self, i):
        return 2 * i + 2

    def PARENT(self, i):
        return (i - 1) / 2

    def MIN_HEAPIFY(self, i):
        # 最小堆化:使以i为根的子树成为最小堆
        l = self.LEFT(i)
        r = self.RIGHT(i)
        if l < self.heapsize and self.items[l] < self.items[i]:
            smallest = l
        else:
            smallest = i

        if r < self.heapsize and self.items[r] < self.items[smallest]:
            smallest = r

        if smallest != i:
            self.items[i], self.items[smallest] = self.items[smallest], self.items[i]
            self.MIN_HEAPIFY(smallest)

    def INSERT(self, val):
        # 插入一个值val,并且调整使满足堆结构
        self.items.append(val)
        idx = len(self.items) - 1
        parIdx = self.PARENT(idx)
        while parIdx >= 0:
            if self.items[parIdx] > self.items[idx]:
                self.items[parIdx], self.items[idx] = self.items[idx], self.items[parIdx]
                idx = parIdx
                parIdx = self.PARENT(parIdx)
            else:
                break
        self.heapsize += 1

    def DELETE(self):
        last = len(self.items) - 1
        if last < 0:
            # 堆为空
            return None
        # else:
        self.items[0], self.items[last] = self.items[last], self.items[0]
        val = self.items.pop()
        self.heapsize -= 1
        self.MIN_HEAPIFY(0)
        return val

    def BUILD_MIN_HEAP(self):
        # 建立最小堆, O(nlog(n))
        i = self.PARENT(len(self.items) - 1)
        while i >= 0:
            self.MIN_HEAPIFY(i)
            i -= 1

    def SHOW(self):
        print self.items

class ZPriorityQ(ZHeap):
    def __init__(self, item=[]):
        ZHeap.__init__(self, item)

    def enQ(self, val):
        ZHeap.INSERT(self, val)

    def deQ(self):
        val = ZHeap.DELETE(self)
        return val

class MaxHeap:
    def __init__(self, data):
        data.insert(0, None)
        self.heap = data
        self.heapSize = 0
        for i in range(1,len(self.heap)):
            self.heapSize += 1
            self.__bubble(i)

    def __sink(self, pos):
        left, right = 2*pos, 2*pos+1
        next = pos
        if left <= self.heapSize and self.compare(self.heap[left], self.heap[next]) > 0:
            next = left
        if right <= self.heapSize and self.compare(self.heap[right], self.heap[next]) > 0:
            next = right
        if next == pos:
            return
        self.__exchange(pos, next)
        return self.__sink(next)

    def __bubble(self, pos): # build
        if pos <= 1:
            return
        ppos = pos/2
        if self.compare(self.heap[pos], self.heap[ppos]) > 0:
            self.__exchange(pos, ppos)
            return self.__bubble(ppos)

    def compare(self, a, b):
        return a - b

    def __exchange(self, i, j):
        temp = self.heap[i]
        self.heap[i] = self.heap[j]
        self.heap[j] = temp

    def sort(self):
        while self.heapSize > 1:
            self.__exchange(1, self.heapSize)
            self.heapSize -= 1
            self.__sink(1)
        self.heap.remove(None)
        return self.heap

2. 实现堆排序

def sift_down(arr, start, end):

    root = start

    while True:

        # 从root开始对最大堆调整

        child = 2 * root + 1

        if child > end:

            break

        # 找出两个child中交大的一个

        if child + 1 <= end and arr[child] < arr[child + 1]:

            child += 1

        if arr[root] < arr[child]:

            # 最大堆小于较大的child, 交换顺序

            arr[root], arr[child] = arr[child], arr[root]

            # 正在调整的节点设置为root

            root = child

        else:

            # 无需调整的时候, 退出

            break

def heap_sort(arr):

    # 从最后一个有子节点的孩子还是调整最大堆

    first = len(arr) // 2 - 1

    for start in range(first, -1, -1):

        sift_down(arr, start, len(arr) - 1)

    # 将最大的放到堆的最后一个, 堆-1, 继续调整排序

    for end in range(len(arr) -1, 0, -1):

        arr[0], arr[end] = arr[end], arr[0]

        sift_down(arr, 0, end - 1)

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

class Solution:
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """

        heap = []
        for ln in lists:
            if ln:
                heap.append((ln.val, ln))
        dummy = ListNode(0)
        cur = dummy
        heapq.heapify(heap)
        while heap:
            valu, ln_index = heapq.heappop(heap)
            cur.next = ln_index
            cur = cur.next
            if ln_index.next:
                heapq.heappush(heap, (ln_index.next.val, ln_index.next))
        return dummy.next

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

def findKthLargest(self, nums, k):
        import heapq
        return heapq.nlargest(k, nums)[-1]

  练习:

  路径总和 https://leetcode-cn.com/problems/path-sum/

  思路:递归

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

原文地址:https://www.cnblogs.com/deeplearning-man/p/10884763.html

时间: 2024-08-28 17:45:19

数据结构与算法:二叉树+堆的相关文章

javascript数据结构与算法--二叉树(插入节点、生成二叉树)

javascript数据结构与算法-- 插入节点.生成二叉树 二叉树中,相对较小的值保存在左节点上,较大的值保存在右节点中 /* *二叉树中,相对较小的值保存在左节点上,较大的值保存在右节点中 * * * */ /*用来生成一个节点*/ function Node(data, left, right) { this.data = data;//节点存储的数据 this.left = left; this.right = right; this.show = show; } function sh

[数据结构与算法] 二叉树及其遍历方式

声明:原创作品,转载时请注明文章来自SAP师太技术博客:www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4289830.html 一.数据结构分类 (一)按逻辑结构 集合(无辑关系) 线性结构(线性表):数组.链表.栈.队列 非线性结构:树.图.多维数组 (二)按存储结构 顺序(数组)储结构.链式储结构.索引储结构.散列储结构 二.二叉树相关性质

数据结构与算法 —— 二叉树

二叉树 定义: 来自于百度百科. 在计算机科学中,二叉树是每个节点最多有两个子树的树结构.通常子树被称作"左子树"(left subtree)和"右子树"(right subtree).二叉树常被用于实现二叉查找树和二叉堆. 二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒.二叉树的第i层至多有2^{i-1}个结点:深度为k的二叉树至多有2^k-1个结点:对任何一棵二叉树T,如果其终端结点数为n_0,度为2的结点数为n_

数据结构与算法之堆与堆排序

在数据结构中,堆其实就是一棵完全二叉树.我们知道内存中也有一块叫做堆的存储区域,但是这与数据结构中的堆是完全不同的概念.在数据结构中,堆分为大根堆和小根堆,大根堆就是根结点的关键字大于等于任一个子节点的关键字,而它的左右子树又分别都是大根堆:小根堆与大根堆恰好相反.在C++的STL中优先队列priority_queue结构就是实现的堆结构.下来自己动手现实一个堆结构,包括heap_init,heap_insert,heap_top等操作. 1.堆的实现 因为堆是一棵完全二叉树,所以我们可以用顺序

数据结构与算法--二叉树(一)

1 基于二叉链表的有序二叉树 1.1 问题 BST是Binary Search Tree的缩写,译为二叉搜索树,或有序二叉树,是二叉树的一种,它的定义如下: 1)或者是一棵空树: 2)或者是具有下列性质的二叉树: I) 若左子树不空,则左子树上所有结点的值均小于它的根结点的值: II) 若右子树不空,则右子树上所有结点的值均大于它的根结点的值: III)左.右子树也分别为二叉排序树: BST在查找一个结点或插入一个结点时,具有极大的优势,速度非常快.是一种基础性数据结构,广泛应用于更加抽象的集合

小甲鱼数据结构和算法-----二叉树的构建和前序遍历

题目要求:建立二叉树并输出每个字符所在的层数.如下图要求输出 A 在第一层 B.C 在第二层 D.E在第三层 代码如下: #include <stdio.h> #include <stdlib.h> typedef struct BiTNode { char data; struct BiTNode *lchild,*rchild; }BiTNode,*BiTree; // 创建一棵二叉树,约定用户遵照前序遍历的方式输入数据 void CreateBiTree(BiTree *T)

数据结构和算法——二叉树

树1.树的优点有序数组: 查找很快,二分法实现的查找所需要的时间为O(logN),遍历也很快,但是在有序数组中插入,删除却需要先 找到位置, 在把数组部分元素后移,效率并不高. 链表: 链表的插入和删除都是很快速的,仅仅需要改变下引用值就行了,时间仅为O(1),但是在链表中查找数据却需要遍历所有的元素, 这个效率有些慢了.树的优点: 树结合了有序数组和链表的优点,可以实现快速的查找,也可以快速的删除,查找. 树的一些专用术语: 路径: 顺着连接节点的边从一个节点到另一个节点的,所经过的所有节点的

python数据结构与算法——二叉树结构与遍历方法

先序遍历,中序遍历,后序遍历 ,区别在于三条核心语句的位置 层序遍历  采用队列的遍历操作第一次访问根,在访问根的左孩子,接着访问根的有孩子,然后下一层 自左向右一一访问同层的结点 # 先序遍历 # 访问结点,遍历左子树,如果左子树为空,则遍历右子树, # 如果右子树为空,则向上走到一个可以向右走的结点,继续该过程 preorder(t):    if t:       print t.value       preorder t.L       preorder t.R # 中序遍历 # 从根

java数据结构和算法------二叉树基本操作

1 package iYou.neugle.tree; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 public class Binary_Tree<T> { 7 private Tree tree = new Tree(); 8 9 class Tree { 10 public T data; 11 public Tree left; 12 public Tree right; 13 } 14 15 public

js数据结构和算法---二叉树

原文: https://segmentfault.com/a/1190000000740261 //前序遍历 function preOrder(node) { if (node != null) { node.style.background = "black"; setTimeout(function () { preOrder(node.children[0]); },1500); setTimeout(function () { preOrder(node.children[1