归并排序 ---实践篇

大纲

  1. 基本的归并排序
  2. 合并K个有序数组

1.基本的归并排序

def merge(a, b):
    c = []
    i = j = 0
    while i < len(a) and j < len(b):
        if a[i] <= b[j]:
            c.append(a[i])
            i += 1
        else:
            c.append(b[j])
            j += 1
    
    if i == len(a):
        c = c + b[j:]
    else:
        c = c + a[i:]
    return c

def merge_sort(arr):
    # 这里的判断语句就是跳出递归的条件
    if len(arr) <= 1:
        return arr
    mid = int(len(arr) / 2)
    left = merge_sort(arr[:mid])
    right = merge_sort(arr[mid:])
    return merge(left, right)

时间复杂度, 其实每层的比较次数(或者说遍历次数)没变,即需要比较n次,一共是logn层,因此复杂度为.

2.合并K个有序数组

由于数组是有序的,因此每次直接比较每个数组中的最小值,然后依次排序即可。其实,每次从K个数组中选出最小值的时候,候选数组中只有最小值被提取出,其他值都不变,因此这个过程和最小堆出队很像。因此,如果利用最小堆,我们可以将选出最小值的复杂度从降低到

# -*- coding:utf-8 -*-
from collections import namedtuple

Item = namedtuple("Item", ["array_index", "value"])

class MinHeap(object):
    def __init__(self):
        self.heap = []
        self.size = 0

    def top(self):
        return self.heap[0]
 
    def _adjust_heap(self, begin, end):
        root = begin
        while True:
            child = root * 2 + 1
            if child > end:
                break
            if child + 1 <= end and self.heap[child+1].value < self.heap[child].value:
                child = child + 1
            if self.heap[root].value > self.heap[child].value:
                self.heap[root], self.heap[child] = self.heap[child], self.heap[root]
                root = child
            else:
                break

    def add(self, item):
        self.heap.append(item)
        self.size += 1
        self._adjust_heap(0, self.size-1)
 
    def pop_add(self, item):
        self.heap[0] = item
        self._adjust_heap(0, self.size-1)

    def pop(self):
        self.heap[0], self.heap[self.size-1] = self.heap[self.size-1], self.heap[0]
        self.size -= 1
        #self.heap = self.heap[:self.size]
        self._adjust_heap(0, self.size-1)


def merge_k_sorted_list(arrays, k):
    indices = [0] * k
    sizes = [len(array) for array in arrays]
    total_size = sum(sizes)
    mins = MinHeap()
    results = []
    for ind, array in enumerate(arrays):
        mins.add(Item(ind, array[0]))
 
    while len(results) < total_size:
        _array_ind, _min_value = mins.top()
        results.append(_min_value)
        indices[_array_ind] += 1
        if indices[_array_ind] < sizes[_array_ind]:
            _candidate_value = arrays[_array_ind][indices[_array_ind]]
            mins.pop_add(Item(_array_ind, _candidate_value))
        else:
            mins.pop()
    return results


if __name__ == "__main__":
    arrays = [[1, 3, 5],
            [2, 4, 6, 9, 10],
            [3, 7, 8, 13]]
    arrays = [[1, 4, 7],
            [2, 5, 8],
            [3, 6, 9, 10, 13]]
    arrays = [[1, 4, 7], 
            [2, 5, 8], 
            [14, 15, 16, 17, 18, 19],
            [3, 6, 9, 10, 13]]
    k = len(arrays) 
    print merge_k_sorted_list(arrays, k)

你可能感兴趣的:(归并排序 ---实践篇)