一、队列

1、概念

队列是一种先进先出的线性表。
它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
如图所示
队列及堆排序学习笔记

2、python的实现

#通过 Queue() 建立一个空队列
class Queue:
    def __init__(self):
        self.items=[]
#判断队列是否为空
    def is_empty(self):
        return self.items==[]
	#将新元素插入到列尾
    def enqueue(self,item):
        self.items.insert(0,item)
	#将弹出并删除队首的元素
    def dequeue(self):
        return self.items.pop()
#返回队列的大小
    def size(self):
        return  len(self.items)

二、堆排序

1、概念

堆栈是计算机的两种最基本的数据结构。堆的特点就是FIFO(first in first out)先进先出,可以理解成树的结构。堆在接收数据的时候先接收的数据会被先弹出。
栈的特性正好与堆相反,是属于FILO(first in/last out)先进后出的类型。栈处于一级缓存而堆处于二级缓存中。

2、堆节点的访问

通常堆是通过一维数组来实现的。在阵列起始位置为0的情况中

  • 父节点i的左子节点在位置(2*i+1)
  • 父节点i的右子节点在位置(2*i+2)
  • 子节点i的父节点在位置floor((i-1)/2)

3、堆操作

  • 最大堆调整(MAX_Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点。这是核心步骤,在建堆和堆排序都会用到。比较i的根节点和与其所对应i的孩子节点的值。当i根节点的值比左孩子节点的值要小的时候,就把i根节点和左孩子节点所对应的值交换,当i根节点的值比右孩子的节点所对应的值要小的时候,就把i根节点和右孩子节点所对应的值交换。然后再调用堆调整这个过程,可见这是一个递归的过程。
  • 建立最大堆(Build_Max_Heap):将堆所有数据重新排序。建堆的过程其实就是不断做最大堆调整的过程,从len/2出开始调整,一直比到第一个节点。
  • 堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整的递归运算。堆排序是利用建堆和堆调整来进行的。首先先建堆,然后将堆的根节点选出与最后一个节点进行交换,然后将前面len-1个节点继续做堆调整的过程。直到将所有的节点取出,对于n个数我们只需要做n-1次操作。

4、代码实现

import random
def MAX_Heapify(heap,HeapSize,root):#在堆中做结构调整使得父节点的值大于子节点
    left = 2*root + 1
    right = left + 1
    larger = root
    if left < HeapSize and heap[larger] < heap[left]:
        larger = left
    if right < HeapSize and heap[larger] < heap[right]:
        larger = right
    if larger != root:#如果做了堆调整则larger的值等于左节点或者右节点的,这个时候做对调值操作
        heap[larger],heap[root] = heap[root],heap[larger]
        MAX_Heapify(heap, HeapSize, larger)

def Build_MAX_Heap(heap):#构造一个堆,将堆中所有数据重新排序
    HeapSize = len(heap)#将堆的长度当独拿出来方便
    for i in xrange((HeapSize -2)//2,-1,-1):#从后往前出数
        MAX_Heapify(heap,HeapSize,i)

def HeapSort(heap):#将根节点取出与最后一位做对调,对前面len-1个节点继续进行对调整过程。
    Build_MAX_Heap(heap)
    for i in range(len(heap)-1,-1,-1):
        heap[0],heap[i] = heap[i],heap[0]
        MAX_Heapify(heap, i, 0)
    return heap

if __name__ == '__main__':
    a = [30,50,57,77,62,78,94,80,84]
    print(a)
    HeapSort(a)
    print(a)
    b = [random.randint(1,1000) for i in range(1000)]
    print(b)
    HeapSort(b)
    print(b)

三、编程练习

  • 题目
    给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口 k 内的数字。滑动窗口每次只向右移动一位。返回滑动窗口最大值。

  • 示例
    输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
    输出: [3,3,5,5,6,7]
    解释:

    滑动窗口的位置 最大值


[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7

  • 思路
    窗口的滑动过程中数字的进出类似一个队列中元素的出队入队,采用一个队列queue存储可能成为最大值的元素下标。如果每次入队的新元素比队尾元素小,则将其删除,直至队尾元素大于新元素或队空。(因为被删除元素既没有当前元素大,也没有当前元素新,所以肯定不会替代当前元素成为最大值的)
    找最大值时从队头开始,如果队头元素对应的index不在当前窗口则将其删除,直到找到在窗口中的元素,即为最大值。

  • 代码如下

class Solution(object):
    def maxSlidingWindow(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        if not nums: 
            return [] 
        from collections import deque 
        dq = deque() 
        n = len(nums) 
        ans = [] 
        for i in range(k-1): 
            while len(dq) > 0: 
                if nums[dq[-1]] <= nums[i]: 
                    dq.pop() 
                else: 
                    break 
            dq.append(i) 
        for i in range(k-1, n): 
            while len(dq) > 0: 
                if nums[dq[-1]] <= nums[i]: 
                    dq.pop() 
                else: 
                    break 
            dq.append(i) 
            while dq[0] < i-k+1: 
                dq.popleft() 
            ans.append(nums[dq[0]]) 
        return ans
  • 运行结果
    队列及堆排序学习笔记

四、回顾往期内容

https://blog.csdn.net/weixin_44154393/article/details/85074452
https://blog.csdn.net/weixin_44154393/article/details/85089420

注:
本文部分内容参考:
https://blog.csdn.net/minxihou/article/details/51850001
https://blog.csdn.net/songyunli1111/article/details/79344594
推荐参考:
https://www.jianshu.com/p/d174f1862601

相关文章:

  • 2021-12-24
  • 2022-12-23
  • 2021-11-29
  • 2022-12-23
  • 2021-10-04
  • 2021-08-03
  • 2021-06-13
  • 2022-12-23
猜你喜欢
  • 2021-10-06
  • 2022-12-23
  • 2021-09-28
  • 2022-01-17
  • 2021-11-17
  • 2021-11-30
相关资源
相似解决方案