📜  数据结构|堆叠问题3(1)

📅  最后修改于: 2023-12-03 15:40:01.138000             🧑  作者: Mango

数据结构 - 堆叠问题3

概述

堆叠问题3是一类经典的数据结构问题,主要关注如何使用堆或栈来解决相关问题。在该问题中,我们需要处理一系列元素,这些元素可以看做是一个序列。我们需要将这些元素存储到一个数据结构中,并进行操作。堆叠问题3可以被用于许多具体的应用领域,如操作系统进程调度、算法排序、路由算法等。

堆与栈

在解决堆叠问题3时,常用到的两种数据结构是堆和栈。堆是一个树形结构,它是一个完全二叉树,每个节点都比它的子节点大或小。堆常用于优先队列的实现,它可以在常数时间内找到最大或最小元素。栈则是一个后进先出(Last-In-First-Out)的数据结构,可以用数组或链表实现。栈通常用于计算机内存中的调用栈,或者用于编译器实现语法分析时的语法栈。

解决方案
使用堆

当我们需要维护一组元素,每当新元素加入时我们需要找到当前堆中的最小值或最大值时,我们可以使用堆来存储这些元素。以最小堆为例,我们可以定义一个大小为n的数组,用于存储每个元素。我们可以将数组中的第一个元素作为堆顶,同时每个节点的父节点是该节点的(e.g. i) // 2,左子节点是2i,右子节点是2i+1。然后,我们从下标为n/2的节点开始,向下比较,将最小的子节点与该节点进行交换,直到堆的性质被满足为止。插入一个元素时,我们可以将此新元素插入堆底,并将其向上移动直到堆的性质被满足。删除一个元素时,我们可以将堆底的元素移动到堆顶,然后向下移动直到堆的性质被满足。这样,我们可以在O(log n)的时间内找到最小元素,并在O(log n)的时间内插入与删除一个元素。

使用栈

当我们需要维护一组元素,每当新元素加入时需要对当前元素进行某些操作时,我们可以使用栈来存储这些元素。以计算器程序为例,我们可以将输入的中缀表达式转换为后缀表达式,并使用栈进行计算。在这个计算器程序中,我们可以维护两个栈:一个用于存储操作数,另一个用于存储运算符。我们遍历后缀表达式,如果当前字符是数字,我们将其加入操作数栈中;如果当前字符是符号,我们从操作数栈中弹出两个元素,并将计算结果压入操作数栈中;如果当前字符是括号,我们将其压入运算符栈中。最后,我们从操作数栈中弹出结果并返回。这样,我们可以使用栈在O(n)的时间复杂度内完成计算。

代码片段
使用堆
class MinHeap:
    def __init__(self):
        self.heap = [0]
        self.size = 0
        
    def insert(self, item):
        self.heap.append(item)
        self.size += 1
        self._percolate_up(self.size)
    
    def _percolate_up(self, i):
        while i // 2 > 0:
            if self.heap[i] < self.heap[i // 2]:
                self.heap[i], self.heap[i // 2] = self.heap[i // 2], self.heap[i]
            i = i // 2
        
    def delete_min(self):
        min_val = self.heap[1]
        self.heap[1] = self.heap[self.size]
        self.size -= 1
        self.heap.pop()
        self._percolate_down(1)
        return min_val
    
    def _percolate_down(self, i):
        while (i * 2) <= self.size:
            mc = self._min_child(i)
            if self.heap[i] > self.heap[mc]:
                self.heap[i], self.heap[mc] = self.heap[mc], self.heap[i]
            i = mc
    
    def _min_child(self, i):
        if i * 2 + 1 > self.size:
            return i * 2
        else:
            if self.heap[i*2] < self.heap[i*2+1]:
                return i * 2
            else:
                return i * 2 + 1
使用栈
def evaluate_postfix(expr):
    stack = []
    for char in expr:
        if char.isdigit():
            stack.append(int(char))
        else:
            op2 = stack.pop()
            op1 = stack.pop()
            res = do_math(char, op1, op2)
            stack.append(res)
    return stack.pop()

def do_math(op, op1, op2):
    if op == '+':
        return op1 + op2
    elif op == '-':
        return op1 - op2
    elif op == '*':
        return op1 * op2
    else:
        return op1 // op2