Python 數據流中的中位數

如何得到一個數據流中的中位數?如果從數據流中讀出奇數個數值,那麼中位數就是所有數值排序之後位於中間的數值。如果從數據流中讀出偶數個數值,那麼中位數就是所有數值排序之後中間兩個數的平均值。我們使用Insert()方法讀取數據流,使用GetMedian()方法獲取當前讀取數據的中位數

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.littlevalueMaxHeap = []
        self.bigvalueMinHeap = []
        self.maxHeapCount = 0
        self.minHeapCount = 0

    def Insert(self, num):
        if self.minHeapCount < self.maxHeapCount:
            self.minHeapCount +=1
            if num < self.littlevalueMaxHeap[0]:
                tmpNum = self.littlevalueMaxHeap[0]
                self.adjustMaxHeap(num)
                self.createMinHeap(tmpNum)
            else:
                self.createMinHeap(num)
        else:
            self.maxHeapCount+=1
            if len(self.littlevalueMaxHeap)==0:
                self.createMaxHeap(num)
            else:
               if self.bigvalueMinHeap[0]<num:
                    tmpNum=self.bigvalueMinHeap[0]
                    self.adjustMinHeap(num)
                    self.createMaxHeap(tmpNum)
               else:
                   self.createMaxHeap(num)


    def GetMedian(self):
        if self.minHeapCount<self.maxHeapCount:
            return self.littlevalueMaxHeap[0]
        else:
            return (self.littlevalueMaxHeap[0]+self.bigvalueMinHeap[0])/2

    def createMaxHeap(self, num):
        self.littlevalueMaxHeap.append(num)
        tmpIndex = len(self.littlevalueMaxHeap) - 1
        while tmpIndex:
            parentIndex = (tmpIndex - 1) // 2
            if self.littlevalueMaxHeap[parentIndex] < self.littlevalueMaxHeap[tmpIndex]:
                self.littlevalueMaxHeap[parentIndex], self.littlevalueMaxHeap[tmpIndex] =\
                    self.littlevalueMaxHeap[tmpIndex], self.littlevalueMaxHeap[parentIndex]
                tmpIndex=parentIndex
            else:
                break

    def adjustMaxHeap(self,num):
        if num<self.littlevalueMaxHeap[0]:
            self.littlevalueMaxHeap[0]=num
            maxHeapLen = len(self.littlevalueMaxHeap)
            tmpIndex=0
            while tmpIndex< maxHeapLen:
                leftIndex = tmpIndex*2+1
                rightIndex = tmpIndex*2+2
                largerIndex = 0
                if rightIndex <  maxHeapLen:
                    largerIndex = rightIndex if self.littlevalueMaxHeap[leftIndex]<self.littlevalueMaxHeap[rightIndex] else leftIndex
                elif leftIndex < maxHeapLen:
                    largerIndex = leftIndex
                else:
                    break

                if self.littlevalueMaxHeap[tmpIndex] <self.littlevalueMaxHeap[largerIndex]:
                    self.littlevalueMaxHeap[tmpIndex], self.littlevalueMaxHeap[largerIndex] = self.littlevalueMaxHeap[largerIndex], self.littlevalueMaxHeap[tmpIndex]
                    tmpIndex = largerIndex
                else:
                    break


    def createMinHeap(self, num):
        self.bigvalueMinHeap.append(num)
        tmpIndex = len(self.bigvalueMinHeap) - 1
        while tmpIndex:
            parentIndex = (tmpIndex - 1) // 2
            if self.bigvalueMinHeap[tmpIndex]<self.bigvalueMinHeap[parentIndex] :
                self.bigvalueMinHeap[parentIndex], self.bigvalueMinHeap[tmpIndex] = \
                    self.bigvalueMinHeap[tmpIndex], self.bigvalueMinHeap[parentIndex]
                tmpIndex=parentIndex
            else:
                break

    def adjustMinHeap(self,num):
        if num<self.bigvalueMinHeap[0]:
            self.bigvalueMinHeap[0]=num
            minHeapLen = len(self.bigvalueMinHeap)
            tmpIndex=0
            while tmpIndex< minHeapLen:
                leftIndex = tmpIndex*2+1
                rightIndex = tmpIndex*2+2
                smallerIndex = 0
                if rightIndex <  minHeapLen:
                    smallerIndex = rightIndex if self.bigvalueMinHeap[rightIndex]<self.bigvalueMinHeap[leftIndex] else leftIndex
                elif leftIndex < minHeapLen:
                    smallerIndex = leftIndex
                else:
                    break

                if self.bigvalueMinHeap[smallerIndex] < self.bigvalueMinHeap[tmpIndex]:
                    self.bigvalueMinHeap[tmpIndex], self.bigvalueMinHeap[smallerIndex] = self.bigvalueMinHeap[smallerIndex], self.littlevalueMaxHeap[tmpIndex]
                    tmpIndex = smallerIndex
                else:
                    break


if __name__ == '__main__':
    s=Solution()
    for i in [5,2,3,4,1,6,7,0,8]:
        s.Insert(i)
        print(s.GetMedian())

運行結果爲:

5
3.5
3
3.5
3
3.5
4
3.5
4

將以上代碼封裝,簡潔後的代碼:

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.littlevalueMaxHeap = []
        self.bigvalueMinHeap = []
        self.maxHeapCount = 0
        self.minHeapCount = 0

    def Insert(self, num):
        def cmpMaxHeap(a, b):
            return a > b

        def cmpMinHeap(a, b):
            return a < b

        if self.minHeapCount < self.maxHeapCount:
            self.minHeapCount += 1
            if num < self.littlevalueMaxHeap[0]:
                tmpNum = self.littlevalueMaxHeap[0]
                self.adjustHeap(num, self.littlevalueMaxHeap, cmpMaxHeap)
                self.createHeap(tmpNum, self.bigvalueMinHeap, cmpMinHeap)
            else:
                self.createHeap(num, self.bigvalueMinHeap, cmpMinHeap)
        else:
            self.maxHeapCount += 1
            if len(self.littlevalueMaxHeap) == 0:
                self.createHeap(num, self.littlevalueMaxHeap, cmpMaxHeap)
            else:
                if self.bigvalueMinHeap[0] < num:
                    tmpNum = self.bigvalueMinHeap[0]
                    self.adjustHeap(num, self.bigvalueMinHeap, cmpMinHeap)
                    self.createHeap(tmpNum, self.littlevalueMaxHeap, cmpMaxHeap)
                else:
                    self.createHeap(num, self.littlevalueMaxHeap, cmpMaxHeap)

    def GetMedian(self):
        if self.minHeapCount < self.maxHeapCount:
            return self.littlevalueMaxHeap[0]
        else:
            return (self.littlevalueMaxHeap[0] + self.bigvalueMinHeap[0]) / 2

    def createHeap(self, num, heap, cmpfun):
        heap.append(num)
        tmpIndex = len(heap) - 1
        while tmpIndex:
            parentIndex = (tmpIndex - 1) // 2
            if cmpfun(heap[tmpIndex], heap[parentIndex]):
                heap[parentIndex], heap[tmpIndex] = heap[tmpIndex], heap[parentIndex]
                tmpIndex = parentIndex
            else:
                break

    def adjustHeap(self, num, heap, cmpFunc):
        if num < heap[0]:
            heap[0] = num
            maxHeapLen = len(heap)
            tmpIndex = 0
            while tmpIndex < maxHeapLen:
                leftIndex = tmpIndex * 2 + 1
                rightIndex = tmpIndex * 2 + 2
                largerIndex = 0
                if rightIndex < maxHeapLen:
                    largerIndex = rightIndex if cmpFunc(heap[rightIndex], heap[leftIndex]) else leftIndex
                elif leftIndex < maxHeapLen:
                    largerIndex = leftIndex
                else:
                    break

                if cmpFunc(heap[largerIndex], heap[tmpIndex]):
                    heap[tmpIndex], heap[largerIndex] = heap[largerIndex], heap[tmpIndex]
                    tmpIndex = largerIndex
                else:
                    break


if __name__ == '__main__':
    s = Solution()
    for i in [5, 2, 3, 4, 1, 6, 7, 0, 8]:
        s.Insert(i)
        print(s.GetMedian())

運行結果爲:

5
3.5
3
3.5
3
3.5
4
3.5
4
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章