Datawhale编程集训第三天

2018-12-20  本文已影响0人  dzpyc

一、队列

1、简介

队列(queue),是先进先出(FIFO, First-In-First-Out)的线性表,在具体应用中通常用链表或者数组来实现,队列只允许在后端(称为rear)进行插入操作,在前端(称为front)进行删除操作,队列的操作方式和堆栈类似,唯一的区别在于队列只允许新数据在后端进行添加。


2、队列的操作

队列的两种主要操作是:向队列中插入新元素和删除队列中的元素。插入操作也叫做入队,删除操作也叫做出队。入队操作在队尾插入新元素,出队操作删除队头的元素。
队列的另外一项重要操作是读取队头的元素。这个操作叫做peek()。该操作返回队头元素,但不把它从队列中删除。

Queue()        定义一个空队列,无参数,返回值是空队列。
enqueue(item)  在队列尾部加入一个数据项,参数是数据项,无返回值。
dequeue()      删除队列头部的数据项,不需要参数,返回值是被删除的数据,队列本身有变化。
isEmpty()      检测队列是否为空。无参数,返回布尔值。
size()         返回队列数据项的数量。无参数,返回一个整数。

队列操作代码:

# -*- coding:utf-8 -*-
class Queue():
 #初始化队列
 def __init__(self,size):
  self.queue=[]
  self.size=size
  self.tail=0
 #判断队列是否为满,为满返回True
 def Full(self):
  if self.tail==self.size:
   return True
  else:
   return False
 #判断队列是否为空,为空返回True
 def Empty(self):
  if self.tail==0:
   return True
  else:
   return False
 #进队
 def queuein(self,content):
  if self.Full():
   print 'The queue is full!'
  else:
   self.queue.append(content)
   self.tail+=1
 #出队
 def queueout(self):
  if self.Empty():
   print 'The queue is empty!'
   return None
  else:
   content=self.queue[0]
   self.queue.pop(0)
   self.tail-=1
   return content
 #遍历队列
 def queueall(self):
  if self.Empty():
   print 'The queue is empty!'
  else:
   for i in range(0,self.tail):
    print self.queue[i]

二、堆排序

1、简介

堆排序是利用堆这种数据结构而设计的一种排序算法。堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。
堆排序是一种选择排序,整体主要由构建初始堆+交换堆顶元素和末尾元素并重建堆两部分组成。其中构建初始堆经推导复杂度为O(n),在交换并重建堆的过程中,需交换n-1次,而重建堆的过程中,根据完全二叉树的性质,[log2(n-1),log2(n-2)...1]逐步递减,近似为nlogn。所以堆排序时间复杂度一般认为就是O(nlogn)级。

2、堆的特点

堆是完全二叉树,又分为大顶堆和小顶堆;大顶堆:每个结点的值都大于或等于其左右叶子结点的值;小顶堆:每个结点的值都小于或等于其左右叶子结点的值。

大根堆
小根堆

3、堆排序的主要思想:

将待排序列构造成一个大顶堆,此时堆顶元素就是整个序列的最大值,将堆顶元素与堆数组的末尾元素进行交换。然后将剩余的n-1个元素重新构造成一个堆,并得到整个序列的次大值。如此反复执行,得到一个有序的序列。

4、代码实现

#_*_coding:utf-8_*_

def sift_down(arr, node, end):
    root = node
    while True:
        # 从root开始对最大堆调整
        child = 2 * root +1  #left child
        if child  > end:
            break
        print("v:",root,arr[root],child,arr[child])
        print(arr)
        # 找出两个child中交大的一个
        if child + 1 <= end and arr[child] < arr[child + 1]: #如果左边小于右边
            child += 1 #设置右边为大
 
        if arr[root] < arr[child]:
            # 最大堆小于较大的child, 交换顺序
            tmp = arr[root]
            arr[root] = arr[child]
            arr[child]= tmp
 
            # 正在调整的节点设置为root
           root = child 
            
        else:
            # 无需调整的时候, 退出
            break
    print('-------------')
 
def heap_sort(arr):
    # 从最后一个有子节点的孩子还是调整最大堆
    first = len(arr) // 2 -1
    for i in range(first, -1, -1):
        sift_down(arr, i, len(arr) - 1)
    #[29, 22, 16, 9, 15, 21, 3, 13, 8, 7, 4, 11]
    print('--------end---',arr)
    # 将最大的放到堆的最后一个, 堆-1, 继续调整排序
    for end in range(len(arr) -1, 0, -1):
        arr[0], arr[end] = arr[end], arr[0]
        sift_down(arr, 0, end - 1)
        

    
array = [16,9,21,13,4,11,3,22,8,7,15,29]
print(array)
heap_sort(array)
print(array)

三、Leetcode编程练习

题目:239 滑动窗口最大值
给定一个数组 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

注意:

你可以假设 k 总是有效的,1 ≤ k ≤ 输入数组的大小,且输入数组不为空。

思路:

  1. 每次入队如果新元素比队尾元素小,则将其删除,直至队尾元素大于新元素或队内无元素。(因为被删除元素既没有当前元素大,也没有当前元素新,所以肯定不会替代当前元素成为最大值的)
  2. 找最大值时从队头开始,如果队头元素对应的index不在当前窗口则将其删除,直到找到在窗口中的元素,即为最大值。

代码:

class Solution:
    def maxSlidingWindow(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        if len(nums) == 0:
            return []
        if k == 0:
            return nums
        from collections import deque
        deq = deque()
        res = []
        L = len(nums)
        for i in range(L):
            while deq and nums[i] > nums[deq[-1]]:
                deq.pop()
            deq.append(i)
            
            if deq[0] < i - k + 1:
                deq.popleft()

            if i >= k - 1:
                res.append(nums[deq[0]])
        return res

运行结果:


参考内容:

https://blog.csdn.net/PKU_Jade/article/details/77934644
http://python.jobbole.com/85264/
https://www.cnblogs.com/linxiyue/p/3556875.html
http://blog.51cto.com/sevenot/2059588
http://python.jobbole.com/87577/
https://www.jianshu.com/p/d174f1862601
http://www.cnblogs.com/terry-c/p/9864994.html
https://www.cnblogs.com/NewsunLs/p/9568126.html
https://www.cnblogs.com/chengxiao/p/6129630.html
https://blog.csdn.net/dujiahaogod/article/details/79688331

上一篇下一篇

猜你喜欢

热点阅读