iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Python3实现快速排序、归并排序、堆
  • 765
分享到

Python3实现快速排序、归并排序、堆

快速 2023-01-31 08:01:13 765人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

# -*- coding: utf-8 -*- # @Time : 2019-03-26 16:46 # @Author : Jayce Wong # @ProjectName : LeetCode # @Fi

# -*- coding: utf-8 -*-
# @Time         : 2019-03-26 16:46
# @Author       : Jayce Wong
# @ProjectName  : LeetCode
# @FileName     : sorting.py
# @Blog         : https://blog.51cto.com/jayce1111
# @GitHub       : Https://github.com/SysuJayce

import random

def quick_sort(data):
    """
    对于每一轮排序,先随机选取范围内的一个下标,该下标对应的值称为主元,然后将小于主元的值挪到主元
    的左边,大于主元的值挪到主元的右边,即确保主元在正确的位置。然后下一轮只需要对主元左边的数组和
    右边的数组分别排序即可,数组大小减为原来的一半。
    每轮排序确定一个主元,该轮排序完成后待排序的两个数组的长度变为原来的一半,可以看做是一个树,
    根节点是原数组,每一轮会分裂一次,每个节点被分裂成2个子节点,直到该节点长度为1,不需再进行排序
    为止,这样就一共需要logN轮,每轮每部需要比较N次,即时间复杂度nlogn
    快排是不稳定排序(相同大小的元素排序后不一定按照原顺序)
    :param data: 待排序的数组
    """
    def sort(start, end):
        pivot = partition(start, end)
        if pivot > start:
            sort(start, pivot - 1)
        if pivot < end:
            sort(pivot + 1, end)

    def partition(start, end):
        idx = random.randint(start, end)  # 随机选择一个idx
        # 先将idx下标所在的值(主元)和末端的值交换
        data[idx], data[end] = data[end], data[idx]
        position = start  # position是下一个小于主元的值应在的位置
        for i in range(start, end):
            # 如果一个值小于主元,则检查它是否在正确的位置,不正确的话则进行调整,使得它落到应在
            # 的位置
            if data[i] < data[end]:
                if i != position:
                    data[position], data[i] = data[i], data[position]
                position += 1
        # 还原主元应在的位置
        data[position], data[end] = data[end], data[position]
        return position

    if not data:
        return
    sort(0, len(data) - 1)

def merge_sort(data):
    """
    先将数组不断进行对半分裂直到不可再分(最长子数组长度为1),然后进行归并,归并的时候每次从两个
    数组中选择最小的元素。
    归并排序是稳定算法,时间复杂度为nlogn
    :param data: 待排序的数组
    """
    def sort(start, end):
        if start < end:
            mid = (start + end) >> 1
            sort(start, mid)
            sort(mid + 1, end)
            merge(start, mid, end)

    def merge(start, mid, end):
        p1, p2 = start, mid + 1
        while p1 <= mid and p2 <= end:
            if data[p1] < data[p2]:
                temp.append(data[p1])
                p1 += 1
            else:
                temp.append(data[p2])
                p2 += 1
        if p1 <= mid:
            temp.extend(data[p1: mid + 1])
        if p2 <= end:
            temp.extend(data[p2: end + 1])

        # 【需要将辅助数组中的数还原到data中】
        while temp:
            data[start] = temp.pop(0)
            start += 1

    if not data:
        return
    temp = []  # 建立全局辅助数组,避免递归过程不断创建
    sort(0, len(data) - 1)

def heap_sort(data):
    """
    堆排序是不稳定的一种排序算法,其时间复杂度是O(nlogn)

    当需要升序排序的时候,构建最大堆,反之构建最小堆。

    最大堆的定义是对于每一个非叶子节点,它的值大于等于它的子节点。最小堆的定义类似。

    以升序排序为例,堆排首先是从最后一个非叶子节点开始往左往上构建最大堆,目的是减少重复性工作,
    因为如果自顶向下构建最大堆的话难度大,而自底向上构建最大堆的话在对第x层的某个节点构建最大堆的
    时候可以确保第x+1层及以下的树已满足最大堆的定义
    :param data: 待排序的元素
    """
    def adjustHeap(cur_idx, length):
        """

        :param cur_idx: 待调整的子树的根节点位置
        :param length: 树中剩余的元素个数。随着排序的进行,堆顶元素(根节点)会逐个被删除,
                       导致树中元素不断减少
        """
        temp = data[cur_idx]  # 先记录当前位置的元素
        # 由于最大堆的定义是父节点元素大于等于其子节点元素,因此将当前位置的元素和它的子节点元素
        # 进行大小比较,
        k = 2 * cur_idx + 1  # 左子节点的位置
        while k < length:  # 只在树内遍历
            # 如果右子节点的元素更大,则将k定位到右子节点,
            # 因为父节点的值需要不小于最大子节点的值
            if k + 1 < length and data[k] < data[k + 1]:
                k += 1

            # 如果子节点的元素大于根节点,则将子节点的值赋给父节点
            # 如果这里不使用赋值而是交换的话,会有多余的操作(如果这次调整需要不止一次交换的话)
            if data[k] > temp:
                data[cur_idx] = data[k]
                # 这时cur_idx保存的是temp可能要去到的位置,但是由于还有剩余的孙子节点没有比较
                # 所以这里先不用交换,而是记录下temp可能要去到的位置,最后再将其放到正确的位置
                cur_idx = k
            # 如果上层的子节点已经小于父节点,那么孙子节点一定不会大于父节点,因为我们已经构建了
            # 一个最大堆(在初始化构建最大堆时,我们是从最后一个非子节点开始自底向上构建的,所以
            # 在处理上层节点的时候其下层节点已经是符合最大堆定义的了,因此也符合这里的break条件)
            else:
                break
            # 检查剩余的子节点
            k = 2 * k + 1

        data[cur_idx] = temp  # 将temp元素还原到正确的位置

    if not data:
        return

    """ 初始化构建最大堆 """
    # 从最后一个非叶子节点开始,往左遍历,当第x层遍历完之后从第x-1层的最右边开始往左遍历
    # 每次调整该节点使得满足最大堆的要求
    for i in range((len(data) >> 1) - 1, -1, -1):
        adjustHeap(i, len(data))

    # 从构建好的最大堆取出堆顶元素(也就是最大值),然后放到数组末尾(即将这个节点删除)
    # 删除之后需要重新调整堆的结构以满足最大堆的定义。
    # 由于上一步已经构建了一个最大堆,因此这里只需要对新的根节点的元素进行调整即可
    for j in range(len(data) - 1, 0, -1):
        data[j], data[0] = data[0], data[j]
        adjustHeap(0, j)

def main():
    data = []
    for _ in range(10):
        data.append(random.randint(0, 9))

    print(data)
    quick_sort(data)
    merge_sort(data)
    heap_sort(data)
    print(data)

if __name__ == '__main__':
    main()

--结束END--

本文标题: Python3实现快速排序、归并排序、堆

本文链接: https://www.lsjlt.com/news/192467.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Python3实现快速排序、归并排序、堆
    # -*- coding: utf-8 -*- # @Time : 2019-03-26 16:46 # @Author : Jayce Wong # @ProjectName : leetcode # @Fi...
    99+
    2023-01-31
    快速
  • golang归并排序,快速排序,堆排序的实现
    归并排序 归并排序使用经典的分治法(Divide and conquer)策略。分治法会将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得...
    99+
    2022-11-13
  • Java的堆排序、快速排序、归并排序怎么实现
    本文小编为大家详细介绍“Java的堆排序、快速排序、归并排序怎么实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java的堆排序、快速排序、归并排序怎么实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。堆排序...
    99+
    2023-06-26
  • Java综合整理堆排序 快速排序 归并排序
    目录堆排序快速排序递归非递归归并排序递归非递归堆排序 时间复杂度:0(N*log(N))空间复杂度:0(1)稳定性:不稳定 private static void heapSort...
    99+
    2022-11-13
  • Java归并排序和快速排序怎么实现
    本篇内容介绍了“Java归并排序和快速排序怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!归并排序// 归并排序 ...
    99+
    2023-06-04
  • 数据结构:直接插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序,计数排序(C实现)
    个人主页 : 个人主页 个人专栏 : 《数据结构》 《C语言》 文章目录 前言一、插入排序1.直接插入排序2.希尔排序 二、选择排序1. 选择排序2.堆排序 三、交换排序1.冒...
    99+
    2023-09-14
    数据结构 c语言 排序算法
  • 八大排序(三)堆排序,计数排序,归并排序
    一、堆排序 什么是堆排序:堆排序(Heap Sort)就是对直接选择排序的一种改进。此话怎讲呢?直接选择排序在待排序的n个数中进行n-1次比较选出最大或者最小的,但是在选出最大或者最小的数后,并没有对原来的序列进行改变,这使得下一次选数时还...
    99+
    2023-10-21
    算法 数据结构
  • C++归并法+快速排序实现链表排序的方法
    本文主要介绍了C++归并法+快速排序实现链表排序的方法,分享给大家,具体如下: 我们可以试用归并排序解决: 对链表归并排序的过程如下。 找到链表的中点,以中点为分界,将链表拆分成...
    99+
    2022-11-12
  • Java快速排序与归并排序及基数排序图解示例
    目录一、快速排序1、基本介绍2、代码实现二、归并排序1、基本介绍2、代码实现三、基数排序1、基本介绍2、代码实现一、快速排序 1、基本介绍 以上面的数组为例分析快速排序。 首先要...
    99+
    2022-11-13
  • Java实现快速排序和堆排序的示例代码
    目录快速排序算法步骤动图演示JavaScript代码实现python代码实现Go代码实现C++代码实现Java代码实现堆排序算法步骤动图演示JavaScript代码实现Python代...
    99+
    2022-12-22
    Java快速排序 Java 堆排序 Java排序
  • python中归并排序和快速排序有什么区别
    python中归并排序和快速排序有什么区别?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。在预期情况下的快速排序和归并排序时间复杂度都一样, 在空间复杂度上,没使...
    99+
    2023-06-15
  • Java 归并排序算法、堆排序算法实例详解
    基本思想:  归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。归并排序示例:合并方法:设r[i…n]由两个有序子表r[i…m...
    99+
    2023-05-31
    java 归并排序 堆排序
  • Java实现插入排序,希尔排序和归并排序
    目录插入排序算法步骤动图演示JavaScript代码实现Python代码实现Go代码实现Java代码实现希尔排序算法步骤JavaScript代码实现python代码实现Go代码实现J...
    99+
    2022-12-22
    Java插入排序 Java希尔排序 Java归并排序 Java排序
  • C#实现归并排序
    什么是归并?即将两个有序的数组归并成一个更大的有序数组。 什么是归并排序?先将要排序的数组递归地分成两半分别排序,然后将结果归并起来。 归并排序能够保证将任意大小为 N 的数组排序所...
    99+
    2022-11-13
  • 归并排序python实现
      归并排序 归并排序在于把序列拆分再合并起来,使用分治法来实现,这就意味这要构造递归算法 首先是一个例子 原序先通过一半一半的拆分,然后: 然后再一步一步的向上合并,在合并的过程中完成了排序,合并排序算法如下: def mer...
    99+
    2023-01-31
    python
  • 快速排序详解(递归实现与非递归实现)
    目录 一、快速排序的基本思想 二、将序列划分成左右区间的常见方法 2.1hoare版本(动图+解释+代码实现) 2.2挖坑法 2.3前后指针法 三、快速排序的初步实现 四、快速排序的优化实现 4.1快排的特殊情况 4.2对区间划分代码的...
    99+
    2023-10-24
    排序算法 算法 数据结构 c++
  • 快速排序python实现
      快速排序 快速排序的实现同样使用分治法,它的原理是从序列中选择一个值作为基准值,然后分成比基准值小的序列集合和比基准值小的序列集合和与基准值相等的序列集合。 再将比基准值小的序列集合和比基准值小的序列集合再次进行选择基准值分割,最...
    99+
    2023-01-31
    快速 python
  • python实现快速排序
    def sortList(alist):    alen = len(alist)    if alen == 0:        return alist    if alen > 0:        aitem = alist[a...
    99+
    2023-01-31
    快速 python
  • python 快速排序实现
    import random num_list = []for x in range(30):    num_list.append(random.randint(1, 500))list_len = ...
    99+
    2023-06-02
  • Java排序算法之归并排序简单实现
    算法描述:对于给定的一组记录,首先将每两个相邻的长度为1的子序列进行归并,得到 n/2(向上取整)个长度为2或1的有序子序列,再将其两两归并,反复执行此过程,直到得到一个有序序列。package sorting;public class M...
    99+
    2023-05-30
    java算法 归并排序 ava
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作