IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 排序算法-堆排序-归并排序-快排 -> 正文阅读

[数据结构与算法]排序算法-堆排序-归并排序-快排

todo: 疑问:本文实现的快排的时间复杂度是O(n*log2(n))吗

特别鸣谢:来自夸夸群的 醉笑陪公看落花@知乎王不懂不懂@知乎QFIUNE@csdn
感谢醉笑陪公看落花@知乎 倾囊相授,感谢小伙伴们督促学习,一起进步

tips

  • 稳定排序
    • 冒泡排序
    • 归并排序
    • 插入排序
  • 不稳定的排序
    • 快排排序
    • 选择排序
      在这里插入图片描述

上图来源 https://www.cnblogs.com/xiaochun126/p/5086037.html

下面介绍集中排序算法的实现,从小到大排序

归并排序 O(n*log2(n))

  • 分:把列表一分为二,得到两个有序列表
  • 治:合并两个有序列表

递归地拆分列表,当拆分出来的列表只含有单个元素的时候,自然是有序的,可以作为递归的终止条件

在这里插入图片描述

'''
归并排序
'''
def mergeSort(nums):
    if len(nums)==1:
        return nums
    s = len(nums)//2
    sa,sb = mergeSort(nums[:s]),mergeSort(nums[s:])
    ans = doMerge(sa,sb)
    return ans
def doMerge(sa,sb):
    ans = []
    i = j = 0
    while(i<len(sa) and j <len(sb)):
        if sa[i]<=sb[j]:  # 等号保证排序稳定(元素相等的时候,sb中的元素插在后面)
            elem = sa[i]
            i+=1
        else:
            elem = sb[j]
            j+=1
        ans.append(elem)
    ans.extend(sa[i:])
    ans.extend(sb[j:])
    return ans

堆排序

堆的性质

堆的实现通过构造二叉堆(binary
heap),实为二叉树的一种;由于其应用的普遍性,当不加限定时,均指该数据结构的这种实现。这种数据结构具有以下性质。

  • 任意节点小于(或大于)它的所有后裔,最小元(或最大元)在堆的根上(堆序性)。
  • 堆总是一棵完全树。即除了最底层,其他层的节点都被元素填满,且最底层尽可能地从左到右填入。

将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。

来源维基百科 堆积 性质

由此可知,大根堆的子树也是大根堆

用数组存一棵完全二叉树,通过下标获取某个已知节点的关联节点

若数组下标从0开始

  1. 已知父节点为i, 则左孩子为:2i+1,右孩子为 2i+2
  2. 已知孩子节点为j,则父节点为 (j-1)//2

若数组下标从1开始

  1. 已知父节点为i, 则左孩子为:2i,右孩子为 2i+1
  2. 已知孩子节点为j,则父节点为 j//2

在这里插入图片描述

本文大根堆数组下标都从0开始

方案1 自底向上调整大根堆O(n^2)

从最后一个非叶结点开始调整,让这个节点比后裔大,一直到root节点比后裔大,再将root节点放在末尾。 这样,最大的数就排在了数组的末尾。再把倒数第二大的数字,放在数组倒数第二的位置,依此类推。

'''
堆排序 -- 自底向上调整
目前时间复杂度:O(n^2)
'''
def heapSort(nums):
    for end in range(len(nums)-1,-1,-1):
        doheapSort(nums,end)
    return nums

def doheapSort(nums,end):
    root = (end-1) // 2  # 最后一个非叶节点的下标
    while(root>=0):
        left = root*2+1
        right = root*2+2
        if nums[left]>nums[root]:
            nums[left], nums[root] = nums[root],nums[left]
        if nums[right] > nums[root] and right<=end:
            nums[right], nums[root] = nums[root], nums[right]
        root-=1
    # root -1 # 倒数第二个非叶节点的下标
    nums[0], nums[end] = nums[end], nums[0]

方案2 自顶向下调整大根堆O(n*log2(n))

先构建一个大根堆(每一个节点都大于等于后裔),把root和数组末尾的值交换,再自顶向下调整(末尾这个数字已经是确保是最大值,因此下一次大根堆的数组不包括原来数组基础上的末尾元素)

'''
O(n*log2(n))
'''
def heapSort(nums):  # O(n * log2(n))
    generateBigheap(nums) # O(n * log2(n))
    for end in range(len(nums)-1,-1,-1): # O(n * log2(n))
        nums[0], nums[end] = nums[end], nums[0]
        down_adjust(nums,0,end-1)
    return nums

def generateBigheap(nums): # O(n * log2(n))
    for root in range((len(nums)-2)//2,-1,-1):
        print(root)
        left = root*2+1
        right = left+1
        maxelem = left if right>len(nums)-1 or nums[right]<nums[left] else right
        if nums[root]>nums[maxelem]:continue
        nums[maxelem], nums[root] = nums[root], nums[maxelem]
        down_adjust(nums, maxelem,len(nums)-1)
def down_adjust(nums,root,end): # O(log2(n))
    while root * 2 + 1 <end:
        left = root * 2 + 1
        right = left + 1
        maxelem = left if right>end or nums[right]<nums[left] else right
        if nums[root] > nums[maxelem]: break
        nums[maxelem], nums[root] = nums[root], nums[maxelem]
        root = maxelem

快排 O(n*log2(n))

主要用到了基准元素和双指针,以及递归思想

  • 双指针移动和 leetcode 11,42,407, 容器,接雨水,二维雨水,坑 文中对墙的移动相似。本文中每次数组被修改位置的指针,向着另一个指针的方向挪动1位
  • 双指针每一次碰头的时候,基准元素到达了最终位置。草图中展示了双指针一次碰头的过程。
  • 找到了最终位置的基准元素将列表一分为二,下一步需要递归地去找下一个基准元素的位置,直到找到所有的基准元素

快排草图

在这里插入图片描述

def quickSort(nums,start,end):
    i = start
    j = end
    if start>=end:return
    base = i
    b = nums[base]
    while i<j:
        while nums[j] >= b and i<j:j-=1
        nums[i] = nums[j]
        while nums[i]<=b and i<j:i+=1
        nums[j] = nums[i]
    nums[i] = b
    quickSort(nums,start,j-1)
    quickSort(nums,j+1,end)

ans = quickSort(nums,0,len(nums)-1)

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-28 08:04:35  更:2021-07-28 08:04:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 17:43:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码