python | 算法-归并排序+小和问题+快排+堆排序


由于python中关于递归有些踩坑,所以不搞对数器,就贴上单个例子验证正确的代码
视频笔记戳这里

1. 归并排序

#归并排序-递归

class solution():
    def mergeSort(self, array):
        """
        归并排序
        :param array: List[int]
        :return: None
        """
        self.process(array, 0, len(array)-1)

    def process(self, array, left, right):
        """
        递归过程
        :param array: List[int]
        :param left: int
        :param right: int
        :return: None
        """
        if left == right: return

        mid = left + (right-left)>>1
        self.process(array, left, mid)
        self.process(array, mid+1, right)
        self.merge(array, left, mid, right)

    def merge(self, array, left, mid, right):
        #整一个辅助空间,存放已经排好序的部分
        help = []
        #比较
        i = left
        j = mid+1
        while i <= mid and j <= right:
            #判断
            if array[i] <= array[j]:
                help.append(array[i])
                i += 1
            else:
                help.append(array[j])
                j += 1
        #谁还剩,就都copy到help中
        while i <= mid:
            help.append(array[i])
            i += 1
        while j <= right:
            help.append(array[j])
            j += 1

        #将help中的排好序的数再copy回array中
        for i in range(len(help)):
            array[left+i] = help[i]

2.归并排序扩展-小和问题

# 归并排序扩展
# 小和问题

class solution():
    def lowerSum(self, array):
        """
        求数组的array的小和
        :param array: List[int]
        :return: int
        """
        if len(array) < 2:
            return 0
        return self.process(array, 0, len(array)-1)

    def process(self, array, left, right):
        """
        递归过程
        :param array: List[int]
        :param left: int
        :param right: int
        :return: int
        """
        if left == right:
            return 0
        mid = left + (right-left)>>1
        return self.process(array, left, mid)+self.process(array, mid+1, right)+self.merge(array, left, mid, right)

    def merge(self, array, left, mid, right):
        """
        将排好序且求出小和的左右两个部分整合
        :param array: List[int]
        :param left: int
        :param mid: int
        :param right: int
        :return: int
        """
        help = []
        sum = 0
        i = left
        j = mid + 1
        while i <= mid and j <= right:
            if array[i] < array[j]:
                sum += array[i]*(right-j+1)
                help.append(array[i])
                i += 1
            else:
                help.append(array[j])
                j += 1

        while i <= mid:
            help.append(array[i])
            i += 1

        while j <= right:
            help.append(array[j])
            j += 1

        for i in range(len(help)):
            array[left+i] = help[i]

        return sum

3.递归-快排

递归方法的快排--真的不适合,查看代码点击这里python
# 递归--快排
import random
class solution():
    def quikSort(self, array):
        """
        用递归和荷兰国旗思想实现的快排
        :param array: List[int]
        :return: None
        """
        self.process(array, 0, len(array)-1)

    def process(self, array, left, right):
        """
        递归过程
        :param array: List[int]
        :param left: int
        :param right: int
        :return: None
        """
        if left < right:
            pick = random.randint(0, len(array) - 1)
            array[pick], array[-1] = array[-1], array[pick]
        p = self.partition(array, left, right)
        self.process(array, left, p[0])
        self.process(array, p[1], right)

    def partition(self, array, left, right):
        """
        荷兰国旗思想
        :param array: List[int]
        :param left: int
        :param right: int
        :return: tmp:List[int]
        """
        i = left-1
        j = right+1
        now = i+1
        one = array[right]
        while now < j :
            if array[now] < one:
                array[now], array[i+1] = array[i+1], array[now]
                now += 1
                i += 1
            elif array[now] == one:
                now += 1
            else:
                array[now], array[j-1] = array[j-1], array[now]
                j -= 1
        return [i, j]

4.堆排序

class heap():
    def swap(self, arr, idx1, idx2):
        """
        将数组arr的两个位置为idx1和idx2的数交换
        :param arr: List[int]
        :param idx1: int
        :param idx2: int
        :return: None
        """
        arr[idx1], arr[idx2] = arr[idx2], arr[idx1]

    def heapInsert(self, arr, idx):
        """
        以大根堆为例
        当前数在数组arr的idx位置,将当前状态恢复成原本大根堆状态
        :param arr: List[int]
        :param idx: int
        :return: None
        """
        dad_idx = int((idx-1)/2)
        while arr[idx] > arr[dad_idx]:
            self.swap(arr, idx, dad_idx)
            idx = dad_idx
            dad_idx = int((idx-1)/2)

    def heapify(self, arr, idx, heapsize): #heapsize便于找到堆的最后一个数
        """
        当前数在数组arr的idx位置
        此函数实现向下调整,以保持大根堆结构
        :param arr:List[int]
        :param idx:int
        :param heapsize:int 当前堆的size
        :return:None
        """
        left = 2 * idx + 1

        while(left < heapsize):
            larger = left+1 if (left+1 < heapsize and arr[left] < arr[left+1]) else left
            if arr[idx] > arr[larger]:
                break
            else:
                self.swap(arr, idx, larger)
                idx = larger
                left = 2 * idx + 1

    def heapSort(self, arr):
        """
        堆排序
        :param arr: List[int]
        :return: None
        """
        if len(arr) < 2: return
        for i in range(len(arr)):
            self.heapInsert(arr, i)

        heapsize = len(arr)
        self.swap(arr, 0, heapsize - 1)
        heapsize -= 1
        while heapsize > 0:
            self.heapify(arr, 0, heapsize)
            self.swap(arr, 0, heapsize - 1)
            heapsize -= 1

4.堆结构的应用

图片名称

    def sortedArrDistanceLessK(self, arr, k):
        """
        已知一个几乎有序的数组arr
        几乎有序是指:如果把数组排好序的话,每个元素移动的距离可以不超过k,并且k相对于数组来说比较小。
        此方法用于对这个数组进行排序。
        默认小根堆
        :param arr: List[int]
        :param k: int
        :return: None
        """
        heap = []
        for i in range(min(len(arr), k)):
            hp.heappush(heap, arr[i]) # import heapq as hp

        j = 0
        while i < len(arr)-1:
            arr[j] = hp.heappop(heap)
            hp.heappush(heap, arr[i])
            j += 1
            i += 1
        while len(heap) != 0:
            arr[j] = hp.heappop(heap)
            j += 1
posted @ 2022-08-10 19:49  万国码aaa  阅读(95)  评论(0编辑  收藏  举报