左程云 基础班 第2讲

左程云 基础班 第2讲

  • 知识点1:荷兰国旗问题
    • 问题:荷兰国旗问题
    • 问题二:荷兰国旗问题
  • 知识点2:快速排序
    • 快速排序
    • 快速排序改进
    • 随机快排
  • 知识点3:完全二叉树
    • 二叉树种类
      • 满二叉树
      • 完全二叉树
  • 知识点4:堆及其堆排序
    • 定义
    • 分类
    • 堆调整
      • 建立大根堆heapInsert
      • 堆调整 heapify
    • 堆排序
      • 大根堆减堆操作
      • 大根堆减堆操作步骤如下
      • 堆排序步骤
      • 问题1:数组中位数

在这小节的代码中,因为对数器器中需要用到随机数,所以导入随机库函数

import random

知识点1:荷兰国旗问题

问题:荷兰国旗问题

给定一个数组arr, 和一个数num, 请把小于等于num的数放在数组的左边, 大于num的数放在数组的右边。
1、要求额外空间复杂度O(1), 时间复杂度O(N)
2、对数器方法要求额外空间复杂度O(N)), 时间复杂度O(N)

def LessMoreNum_right(array,num):
    less=[]
    more=[]
    equal=[]
    for i in range(len(array)):
        if array[i]<num:
            less.append(array[i])
        elif array[i]==num:
            equal.append(array[i])
        elif array[i]>num:
            more.append(array[i])
    return less+equal+more

因为原题只要是将小于num的数移到num的做出即可,并不要求左侧是有序的,所以解题方法有很多种,此时不能直接采用判断新的解题答案和遍历方法得到的结果一致。
结合荷兰国旗问题来求解,主函数入口

#结合荷兰国旗问题来求解,主函数入口
def Netherlands(array,num):
    if array==None:
        return False
    elif len(array)==1 and array[0]!=num:
        return False
    else:
        partition(array=array,left=0,right=len(array)-1,num=num)

荷兰国旗问题处理过程

#交换数组两个下标的数值
def swap(array,index1,index2):
    item=array[index1]
    array[index1]=array[index2]
    array[index2]=item


#荷兰国旗问题处理过程
def partition(array,left,right,num):
    lessIndex=left-1
    moreIndex=right+1
    index=left
    while index<moreIndex:
        if array[index]<num:
            lessIndex=lessIndex+1
            swap(array=array,index1=index,index2=lessIndex)
            index=index+1
        elif array[index]==num:
            index=index+1
        elif array[index]>num:
            moreIndex = moreIndex - 1
            swap(array=array, index1=index, index2=moreIndex)
    return array

问题二:荷兰国旗问题

给定一个数组arr, 和一个数num, 请把小于num的数放在数组的左边, 等于num的数放在数组的中间, 大于num的数放在数组的右边。
要求额外空间复杂度O(1), 时间复杂度O(N)
例子: 给定数组:[2, 3, 1, 9, 7, 6, 1, 4, 5],给定一个值4,那么经过处理原数组可能得一种情况是:[2, 3, 1, 1, 4, 9, 7, 6, 5],需要注意的是,小于4的部分不需要有序,大于4的部分也不需要有序,返回等于4部分的左右两个下标,即[4, 4]
左程云 基础班 第2讲_第1张图片

  1. less 用于记录小于 4 的区域的右下标,初始为-1,代表不存在
  2. more 用于记录大于 4 区域的左下标,初始为9,代表不存在
  3. L 用于正在遍历的元素的下标,初始值为0
  4. 从 arr[L] 即 arr[0] 开始遍历数组
    如果 arr[L] > 4, 交换 arr[++ less] 和 arr[L++] 的值
    如果 arr[L] < 4, 交换 arr[–more] 和 arr[L] 的值
    如果 arr[L] = 4, 不交换,L++,直接遍历下一个值
  5. 当 L >= more,退出循环。

    关键步骤
    假设要进行处理的列表为array,选定的数值为num
    1、在进行列表遍历的时候,当array[i] 2、在进行列表遍历的时候,当array[i]>num时,交换arrayl[more-1]和array[i],然后i保持不变

之所以在两种情况下,进行交换后,对i的处理不同,原因如下:
当遇到>情况的时候,进行数值交换后,此时array[i]的数值在之前的数组遍历的时候没有遇到过,所以在下一步操作中要对其进行判断,所以没有进行i++操作。同理可得,在遇到<情况下,交换数值后,因为此时的array[i]的数值是之前已经遍历过的,所以不需要再进行判断了,直接i++即可。

#交换数组两个下标的数值
def swap(array,index1,index2):
    item=array[index1]
    array[index1]=array[index2]
    array[index2]=item

#荷兰国旗问题处理过程
def partition(array,left,right,num):
    lessIndex=left-1
    moreIndex=right+1
    index=left
    while index<moreIndex:
        if array[index]<num:
            lessIndex=lessIndex+1
            swap(array=array,index1=index,index2=lessIndex)
            index=index+1
        elif array[index]==num:
            index=index+1
        elif array[index]>num:
            moreIndex = moreIndex - 1
            swap(array=array, index1=index, index2=moreIndex)
    return array

知识点2:快速排序

快速排序

经典快排就是将序列中比尾元素小的移动到序列左边,比尾元素大的移动到序列右边,对以该元素为界的左右两个子序列(均不包括该元素)重复此操作。
首先我们要考虑的是对给定的一个数,如何将序列中比该数小的移动到左边,比该数大的移动到右边。
思路: 利用一个辅助指针small,代表较小数的右边界(初始指向首元素前一个位置),遍历序列每次遇到比该数小的数就将其与arr[small+1]交换并右移small,最后将该数与arr[small+1]交换即达到目的。 对应算法如下:

#交换数组两个下标的数值
def swap(array,index1,index2):
    item=array[index1]
    array[index1]=array[index2]
    array[index2]=item

#经典快排
#改进的荷兰国旗问题,返回列表中元素等于最后一位array[R]的下标索引的上下界限
#在荷兰国旗问题的基础上,将 num=array[R],即数组的最后一位
def partition2(array,left,right):
    num=array[right]
    less=left-1
    more=right+1
    index=left   
    while index<more:
        if array[index]==num:
            index=index+1
        elif array[index]<num:
            less=less+1
            swap(array,less,index)
            index=index+1
        elif array[index]>num:
            more=more-1
            swap(array,more,index)
    num_index=[less+1,more-1]
    return num_index

#经典快排
def quick_sort(array,left,right):
    if left<right:
        num_index=partition2(array,left,right)
        quick_sort(array,left,num_index[0]-1)
        quick_sort(array,num_index[1]+1,right)
        return array

经典排序的时间复杂度与数据状况有关,如果每一次partition时,尾元素都是序列中最大或最小的,那么去除该元素序列并未如我们划分为样本量相同的左右两个子序列,而是只安排好了一个元素(就是去掉的那个元素),这样的话时间复杂度就是O(n-1+n-2+……+1)=O(n^2) ;但如果每一次partition时,都将序列分成了两个样本量相差无几的左右两个子序列,那么时间复杂度就是O(nlogn)(使用Master公式求解)。

快速排序改进

比较一下经典排序和使用荷兰国旗问题改进后的经典排序,不难发现,后者一次partition能去除一个以上的元素(等于arr[endIndex]的区域), 而前者每次partition只能去除一个元素,这里的去除相当于安排(排序)好了对应元素的位置。因此后者比经典排序更优,但是优化不大,只是常数时间内的优化,实质上的效率还是要看数据状况(最后的情况为O(nlogn),最坏的情况为O(n^2))。

#经典快速排序,结合荷兰国旗问题,从小到大排序
# 主函数入口
def QuickSort(array,left,right):
    if left==right:
        return array[left]
    if left<right:
        index=Partition(array=array, left=left, right=right)
        QuickSort(array, left, index[0]-1)
        QuickSort(array, index[1]+1, right)
        return array
#交换数组两个下标的数值
def swap(array,index1,index2):
    item=array[index1]
    array[index1]=array[index2]
    array[index2]=item
#荷兰国旗问题处理过程,放回array列表中等于num的下标索引
def Partition(array,left,right):
    num=array[right]
    lessIndex = left - 1
    moreIndex = right + 1
    index = left
    while index < moreIndex:
        if array[index] < num:
            lessIndex = lessIndex + 1
            swap(array=array, index1=index, index2=lessIndex)
            index = index + 1
        elif array[index] == num:
            index = index + 1
        elif array[index] > num:
            moreIndex = moreIndex - 1
            swap(array=array, index1=index, index2=moreIndex)
    index=[lessIndex+1,moreIndex-1]
    return index

随机快排

上面谈到了快排的短板是依赖数据状况,那么我们有没有办法消除这个依赖,让他成为真正的O(nlogn)呢?
事实上,为了让算法中的操作不依托于数据状况(如快排中每一次partition取尾元素作为比较,这就没有规避样本的数据状况,如果尾元素是最大或最小值就成了最坏情况)常常有两种做法:

  1. 使用随机取数
  2. 将样本数据哈希打乱

总结: 随机快排是在经典快排的基础上进行修改。他们之间有以下不同点。

  1. 在经典快排中,采用在荷兰国旗问题的基础上,将 num=array[R],即数组的最后一位
  2. 在随机快排中,采用在荷兰国旗问题的基础上,将 num=array[i].i取值为array下标索引中随机一位
  3. 随机快排的复杂度是一个时间长期期望,复杂度为O(N*logN),但是具体到不同的问题,复杂度可能不一样
  4. 程序编写中时,index会很常见的错误理解为index=0,实际上应该是index=left,在荷兰国旗问题,经典快排,这里定义成index=0是没有问题的,但是随机快排就会报错
  5. 算法复杂度是O(N*logN)
在这里插入代码片#随机快速排序,从小到大排序
# 主函数入口
def RandomQuickSort(array,left,right):
    if left==right:
        return array[left]
    if left<right:
        index=Partition(array=array, left=left, right=right)
        RandomQuickSort(array, left, index[0]-1)
        RandomQuickSort(array, index[1]+1, right)
        return array
#交换数组两个下标的数值
def swap(array,index1,index2):
    item=array[index1]
    array[index1]=array[index2]
    array[index2]=item

def Partition(array,left,right):
    num=array[random.randint(left,right)]
    lessIndex = left - 1
    moreIndex = right + 1
    index = left
    while index < moreIndex:
        if array[index] < num:
            lessIndex = lessIndex + 1
            swap(array=array, index1=index, index2=lessIndex)
            index = index + 1
        elif array[index] == num:
            index = index + 1
        elif array[index] > num:
            moreIndex = moreIndex - 1
            swap(array=array, index1=index, index2=moreIndex)
    index=[lessIndex+1,moreIndex-1]
    return index

经数学论证,由于每一轮partition选出的作为比较对象的数是随机的,即序列中的每个数都有1/n的概率被选上,那么该算法时间复杂度为概率事件,经数学论证该算法的数学期望为O(nlogn)。虽然说是数学期望,但在实际工程中,常常就把随机快排的时间复杂度当做O(nlogn)。

知识点3:完全二叉树

堆结构就是将一颗完全二叉树映射到数组中的一种存储方式。

二叉树种类

满二叉树

国内教程定义:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是(2^k) -1 ,则它就是满二叉树。
左程云 基础班 第2讲_第2张图片

完全二叉树

若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
左程云 基础班 第2讲_第3张图片
在实际工程中,用数组来构建完全二叉树,假设一个下标索引为Index的节点,它有左右儿子节点和父母节点,那么他们之间的下标索引满足下面这个关系:

  1. 左儿子:LeftSonIndex=2*Index+1
  2. 右儿子:RightSonIndex=2*Index+1
  3. 父节点:ParentIndex=(Index-1)//2 (向下整除)

左程云 基础班 第2讲_第4张图片

知识点4:堆及其堆排序

定义

堆就是用数组实现的二叉树,所有它没有使用父指针或者子指针。堆根据“堆属性”来排序,“堆属性”决定了树中节点的位置。

堆的常用方法:

  1. 构建优先队列
  2. 支持堆排序
  3. 快速找出一个集合中的最小值(或者最大值)

分类

堆的分类:堆分为两种,大根堆和小根堆,两者的差别在于节点的排序方式。
**定义:**当堆的每一颗子树(包括树本身)的最大值就是其结点时称为大根堆;相反,当堆的每一颗子树的最小值就是其根结点时称为小根堆。其中大根堆的应用较为广泛,是一种很重要的数据结构。
例子:
左程云 基础班 第2讲_第5张图片
这是一个大根堆,因为每一个父节点的值都比其子节点要大。10 比 7 和 2 都大。7 比 5 和 1都大。

堆调整

heapInsert和heapify
大根堆最重要的两个操作就是heapInsert和heapify,前者是当一个元素加入到大根堆时应该自底向上与其父结点比较,若大于父结点则交换;后者是当堆中某个结点的数值发生变化时,应不断向下与其孩子结点中的最大值比较,若小于则交换。

建立大根堆heapInsert

建立大根堆heapInsert

#交换数组两个下标的数值
def swap(array,index1,index2):
    item=array[index1]
    array[index1]=array[index2]
    array[index2]=item
    
#建立大根堆,向上调整
def HeapInsert(array,index):
    parentIndex=(index-1)//2
    while parentIndex>=0 and array[index]>array[parentIndex]:
        swap(array=array,index1=index,index2=parentIndex)
        index=parentIndex
        parentIndex = (index - 1) // 2

建立大根堆算法复杂度是O(N)
对于一个索引下标为i的节点,假设它前面i-1个节点已经是大根堆,那么对i节点与根节点之间的树高度为logi,那么对i节点进行大根堆排序就是这个节点所在的层与根节点之间的树高度,即log i
所以算法复杂度为:
N=log1+log2+log3+…+logN

堆调整 heapify

堆调整heapify
假设在已经建立好的大根堆上,节点index上的数值突然变小,找到左右儿子节点,和这两个数最大的交换,从而不断往下沉,从而重新变为大根堆。

#交换数组两个下标的数值
def swap(array,index1,index2):
    item=array[index1]
    array[index1]=array[index2]
    array[index2]=item
    
#堆调整,向下调整
def HeapIfy(array,index,heapSize):
    LeftSonIndex=2*index+1
    RightSonIndex=2*index+2
    while LeftSonIndex<=heapSize:    #向下调整的前提是左儿子不越界
        if RightSonIndex>heapSize:   #右儿子越界,只有左儿子节点
            if array[index]<array[LeftSonIndex]:
                swap(array=array,index1=index,index2=LeftSonIndex)
            index=LeftSonIndex
            LeftSonIndex = 2 * index + 1
            RightSonIndex = 2 * index + 2

        else:    #存在右儿子节点
            #获得左右儿子节点的较大值
            if array[LeftSonIndex]>=array[RightSonIndex]:
                bigIndex=LeftSonIndex
            else:
                bigIndex=RightSonIndex
            if array[index]<array[bigIndex]:
                swap(array=array,index1=index,index2=bigIndex)
            index=bigIndex
            LeftSonIndex = 2 * index + 1
            RightSonIndex = 2 * index + 2

堆排序

假设我们要从小排序到大。在了解堆排序前,首先要明白大根堆的堆顶元素是整个数组里面的最大值,在了解这个后才能了解堆排序。

大根堆减堆操作

要在一个原始堆长度为heapsize的大根堆减去一个节点为index的元素,并且让减去元素的大根堆后面还能保持大根堆形式。

大根堆减堆操作步骤如下

  1. 让节点为index的元素和大根堆的最后一个节点互换位置
  2. 将堆的长度heapsize更新为heapsize-1(即抛弃最后一个位置的元素,也就是元素节点为index的元素)
  3. 对新新形成的对进行堆调整步骤,即heapify(array,index)

堆排序步骤

堆排序步骤如下:

  1. 首先原始数组不断吐出数据,让一个大根堆去接受数据,并且让大根堆实时进行heapinsert操作,从而让大根堆继续保持还是大根堆的形式,直到数据接受完毕后。
  2. 将大根堆的堆顶元素和最后一个元素互换,这个时候大根堆的最大值(也就是数组的最大值)移动到了大根堆的末尾。
  3. 然后进行堆调整heapify操作,将堆长度heapsize更新为heapsize-1,让大根堆恢复成还是大根堆的形式,这个时新的大根堆的堆顶元素就是数组的第二大元素。
  4. 以此类推,不断进行堆调整操作,从而对数组进行堆排序
#交换数组两个下标的数值
def swap(array,index1,index2):
    item=array[index1]
    array[index1]=array[index2]
    array[index2]=item
#建立大根堆,向上调整
def HeapInsert(array,index):
    parentIndex=(index-1)//2
    while parentIndex>=0 and array[index]>array[parentIndex]:
        swap(array=array,index1=index,index2=parentIndex)
        index=parentIndex
        parentIndex = (index - 1) // 2
#堆调整,向下调整
def HeapIfy(array,index,heapSize):
    LeftSonIndex=2*index+1
    RightSonIndex=2*index+2
    while LeftSonIndex<=heapSize:    #向下调整的前提是左儿子不越界
        if RightSonIndex>heapSize:   #右儿子越界,只有左儿子节点
            if array[index]<array[LeftSonIndex]:
                swap(array=array,index1=index,index2=LeftSonIndex)
            index=LeftSonIndex
            LeftSonIndex = 2 * index + 1
            RightSonIndex = 2 * index + 2

        else:    #存在右儿子节点
            #获得左右儿子节点的较大值
            if array[LeftSonIndex]>=array[RightSonIndex]:
                bigIndex=LeftSonIndex
            else:
                bigIndex=RightSonIndex
            if array[index]<array[bigIndex]:
                swap(array=array,index1=index,index2=bigIndex)
            index=bigIndex
            LeftSonIndex = 2 * index + 1
            RightSonIndex = 2 * index + 2
#堆调整,从小到大排序,主函数入口
def HeapSort(array):
    if array==None or len(array)<2:
        return array
    heapSize=len(array)-1  #数据堆的长度
    #建立大根堆
    for i in range(len(array)):
        HeapInsert(array=array,index=i)
    while heapSize>=0:
        swap(array=array,index1=0,index2=heapSize)
        heapSize=heapSize-1
        HeapIfy(array=array,index=0,heapSize=heapSize)
    return array

问题1:数组中位数

问题描述: 求一个长度为N的数组数值的中位数

思路一:(一般用来处理静态数据,也就是数据本身不变化)
先对数组进行快速排序,算符复杂度为O(N*log N)
当N为偶数的时候,中位数就排序后数组中间两个数的和再除以2。当N为奇数的时候,中位数就是排序后数组中间那个数值。
思路一的弊端:
每次要查询的时候,都要进行数组排序,不能做到实时查询。

思路二:(一般用来处理动态数据,也就是数据还会不断增加进来)

  1. 采用两个堆结构来存放数组,其中一个是大根堆(用来存放个数N/2的较小的数值),另外一个是一个是小根堆(用来存放个数N/2的较大的数值),
  2. 那么大根堆的堆顶元素就是较小的个数N/2的数组较小数值的最大值,小根堆的堆顶元素就是较大的个数N/2的数组较小数值的最小值。这两个堆顶元素就是这个数组的中位数。
  3. 构建这两个堆的步骤如下:

(a)、数组不断弹出元素来插入到堆里面(array[i for i in range(len(array)-1)] ),第一个元素默认进大根堆。然后在进行插入的时候,若数组的元素小于大根堆的堆顶元素,就进入大根堆,大于大根堆堆顶元素就进入小根堆。
(b)、时刻保持大根堆的元素个数和小根堆的元素个数差值不得大于2,如果大根堆元素个数多,就弹出大根堆的堆顶元素到小根堆的堆顶,然后对这两个堆都进行堆调整(即heapify操作)。

思路一代码

#交换数组两个下标的数值
def swap(array,index1,index2):
    item=array[index1]
    array[index1]=array[index2]
    array[index2]=item
#冒泡排序,从小到大排序
def bubble_sort(array):
    if array==None or len(array)<2:
        return array
    for i in range(len(array)):
        for j in range(len(array)-i-1):
            if array[j]>array[j+1]:
                swap(array=array, index1=j, index2=j + 1)
    return array
#求数组的中位数 测试方法
def GetMidNum(array):
    if array==None or len(array)<2:
        return array
    array=bubble_sort(array)
    return array[(len(array)-1)//2]

思路二代码

#求数组的中位数,对数器方法
def GetMidNum_right(array):
    if array==None or len(array)<2:
        return array
    array=sorted(array)
    return array[(len(array)-1)//2]

大根堆的建立以及堆调整过程代码

###########大根堆的建立以及堆调整过程代码######################
def heapInsert_BigRootPile(array,index):
    parentIndex=(index-1)//2
    while parentIndex>=0 and array[index]>array[parentIndex]:
        swap(array=array,index1=index,index2=parentIndex)
        index=parentIndex
        parentIndex = (index - 1) // 2

def heapIfy_BigRootPile(array,index,heapSize):
    LeftSonIndex = 2 * index + 1
    RightSonIndex = 2 * index + 2
    while LeftSonIndex <= heapSize:  # 向下调整的前提是左儿子不越界
        if RightSonIndex > heapSize:  # 右儿子越界,只有左儿子节点
            if array[index] < array[LeftSonIndex]:
                swap(array=array, index1=index, index2=LeftSonIndex)
            index = LeftSonIndex
            LeftSonIndex = 2 * index + 1
            RightSonIndex = 2 * index + 2

        else:  # 存在右儿子节点
            # 获得左右儿子节点的较大值
            if array[LeftSonIndex] >= array[RightSonIndex]:
                bigIndex = LeftSonIndex
            else:
                bigIndex = RightSonIndex

            if array[index] < array[bigIndex]:
                swap(array=array, index1=index, index2=bigIndex)
            index = bigIndex
            LeftSonIndex = 2 * index + 1
            RightSonIndex = 2 * index + 2

小根堆的建立以及堆调整过程代码

###########小根堆的建立以及堆调整过程代码######################
def heapInsert_SmallRootPile(array,index):
    parentIndex=(index-1)//2
    while parentIndex>=0 and array[index]<array[parentIndex]:
        swap(array=array,index1=index,index2=parentIndex)
        index=parentIndex
        parentIndex = (index - 1) // 2

def heapIfy_SmallRootPile(array,index,heapSize):
    LeftSonIndex = 2 * index + 1
    RightSonIndex = 2 * index + 2
    while LeftSonIndex <= heapSize:  # 向下调整的前提是左儿子不越界
        if RightSonIndex > heapSize:  # 右儿子越界,只有左儿子节点
            if  array[LeftSonIndex]<array[index]:
                swap(array=array, index1=index, index2=LeftSonIndex)
            index = LeftSonIndex
            LeftSonIndex = 2 * index + 1
            RightSonIndex = 2 * index + 2

        else:  # 存在右儿子节点
            # 获得左右儿子节点的较大值
            if array[LeftSonIndex] <= array[RightSonIndex]:
                smallIndex = LeftSonIndex
            else:
                smallIndex = RightSonIndex
            if array[index] > array[smallIndex]:
                swap(array=array, index1=index, index2=smallIndex)
            index = smallIndex
            LeftSonIndex = 2 * index + 1
            RightSonIndex = 2 * index + 2

用堆方法求解数组中位数,主函数

#堆方法求解列表中位数,主函数入口
def GetMidNumHeap(array):
    BigRootPile=[]           #建立所需的大根堆和小根堆
    SmallRootPile=[]
    for i in range(len(array)):

        #先将数据压到对应的数据堆
        if len(BigRootPile)==0:          # 一开始的时候,将元素压到大根堆
            BigRootPile.append(array[i])
        else:
            #当数据小于大根堆堆顶元素的时候,压入大根堆
            #当数据大于小根堆堆顶元素的时候,压入小根堆
            if  len(BigRootPile)!=0 and array[i]<=BigRootPile[0]:
                BigRootPile.append(array[i])
                heapInsert_BigRootPile(array=BigRootPile, index=len(BigRootPile)-1)
            else:
            # elif len(SmallRootPile)!=0 and array[i]>SmallRootPile[0]:
                SmallRootPile.append(array[i])
                heapInsert_SmallRootPile(array=SmallRootPile, index=len(SmallRootPile) - 1)

        #进行堆调整
        # 当len(BigRootPile)-len(SmallRootPile)>=2时,弹出大根堆的堆顶,放到小根堆的堆顶
        #同理可推当当len(SmallRootPile)-len(BigRootPile)>=2
        if len(BigRootPile)-len(SmallRootPile)>=2:
            swap(array=BigRootPile,index1=0,index2=len(BigRootPile)-1)
            item=BigRootPile.pop()
            heapIfy_BigRootPile(array=BigRootPile,index=0,heapSize=len(BigRootPile)-1)

            SmallRootPile.append(item)
            heapInsert_SmallRootPile(array=SmallRootPile, index=len(SmallRootPile)-1)
        elif len(SmallRootPile)-len(BigRootPile)>2:
            swap(array=SmallRootPile, index1=0, index2=len(SmallRootPile) - 1)
            item = SmallRootPile.pop()
            heapIfy_SmallRootPile(array=SmallRootPile, index=0, heapSize=len(SmallRootPile) - 1)

            BigRootPile.append(item)
            heapInsert_BigRootPile(array=BigRootPile, index=len(BigRootPile) - 1)

    #返回数组的中位数
    if len(BigRootPile)-1 ==(len(array)-1)//2:
        return BigRootPile[0]
    else:
        return SmallRootPile[0]

你可能感兴趣的:(数据结构与算法,数据结构,python,算法)