NB三人组

快速排序

  • 思路"

    • 取一个元素P (第一个元素), 使元素归位
    • 列表被P 分成两部分,左边都比P小,右边比P大;
    • 递归完成排序.
  • 问题 如果是已经排序好的 倒叙 列表 则会 递归深度越界
    • 每次
  1. # 时间复杂度: O(n*logn)
  2. import sys
  3. import random
  4. from cal_time import cal_time
  5. # 设置递归深度
  6. sys.setrecursionlimit(10000)
  7. def _quick_sort(li, left, right):
  8. if left < right: # 递归区域至少有两个元素
  9. # 归位 [left, right] --> [left, mid-1] [mid+1, right]
  10. mid = partition(li, left, right)
  11. _quick_sort(li, left, mid-1)
  12. _quick_sort(li, mid+1, right)
  13. @cal_time
  14. def quick_sort(li):
  15. _quick_sort(li, 0, len(li)-1)
  16. def partition(li, left, right):
  17. # 解决最坏情况
  18. # i = random.randint(left, right)
  19. # li[i], li[left] = li[left], li[i]
  20. tmp = li[left]
  21. while left < right:
  22. while left < right and li[right] >= tmp:
  23. right -= 1
  24. li[left] = li[right]
  25. while left < right and li[left] <= tmp:
  26. left += 1
  27. li[right] = li[left]
  28. li[left] = tmp # 此时 left = right
  29. return left
  30. def gogogo2(li, left, right):
  31. # 区域1:[left, i] 区域2:[i+1, j-1]
  32. i = left - 1 # 初识区域1和区域2都空
  33. for j in range(left, right):
  34. if li[j] < li[right]: # 归到区域1
  35. i += 1
  36. li[j], li[i] = li[i], li[j]
  37. li[right], li[i+1] = li[i+1], li[right]
  38. return i+1
  39. @cal_time
  40. def quick_sort2(li):
  41. return _quick_sort2(li)
  42. def _quick_sort2(li):
  43. if len(li) < 2:
  44. return li
  45. x = li[0]
  46. left = [li[i] for i in range(1, len(li)) if li[i] <= x]
  47. right = [li[i] for i in range(1, len(li)) if li[i] > x]
  48. _quick_sort2(left)
  49. _quick_sort2(right)
  50. return left + [x] + right
  51. # @cal_time
  52. # def sys_sort(li):
  53. # li.sort()
  54. import copy
  55. li = list(range(10000))
  56. random.shuffle(li)
  57. li2 = copy.copy(li)
  58. quick_sort(li)
  59. quick_sort2(li2)
  60. # sys_sort(li)
  61. # 另类写法
  62. def my_partition(li, l, r):
  63. a = li[l]
  64. i = l + 1
  65. while i <= r:
  66. if li[i] >= a:
  67. li[r], li[i] = li[i], li[r]
  68. r -= 1
  69. else:
  70. i += 1
  71. li[i - 1], li[l] = li[l], li[i - 1]
  72. return i
  73. def quick_sort(li, left, right):
  74. if left < right:
  75. tmp = my_partition(li, left, right)
  76. quick_sort(li, left, tmp -1)
  77. quick_sort(li, tmp, right)
  78. @cal_time
  79. def _quick_sort(li):
  80. quick_sort(li, 0, len(li) - 1)

堆排序

  • 前传: (树与二叉树简介)

    • 树是一种数据结构 比如目录结构
    • 树是一种可以递归定义的数据结构
    • 树是由N个节点组成的集合
      • 如果n=0,那么是一颗空树:
      • 如果n>0,那么在1个节点作为树的根节点,其他节点可以分为m个集合,每个集合本身又是一棵树.
    • 概念:
      • 根节点,叶子节点
      • 树的深度(高度)
      • 树的度
      • 孩子节点/父节点
      • 子树
  • 时间复杂度 O(n log n)
  1. import random
  2. from cal_time import cal_time
  3. def sift(li, low, high):
  4. # low 表示堆顶下标, high表示堆中最后一个元素下标
  5. tmp = li[low]
  6. i = low
  7. j = 2 * i + 1
  8. while j <= high: # 第二种循环退出情况,没有孩子和tmp竞争i这个位置
  9. if j+1 <= high and li[j+1] > li[j]: # 如果右孩子存在并且比左孩子大 j指向右孩子
  10. j += 1
  11. if li[j] > tmp: # 判断 证明 孩子比父亲大 交换
  12. li[i] = li[j]
  13. i = j # 从新赋值堆顶
  14. j = 2 * i + 1 # 重新赋值孩子
  15. else:
  16. break # 第一种循环退出情况,tmp比目前两个孩子都大
  17. # 将取出的 tmp 从新赋值回空出的位置
  18. li[i] = tmp
  19. @cal_time
  20. def heap_sort(li):
  21. # 1. 从列表构造堆 low的值和high的值
  22. n = len(li)
  23. for low in range(n//2-1, -1, -1):
  24. sift(li, low, n-1)
  25. # 2. 挨个出数 利用原来的空间存储下来的值,但是这些值不属于堆
  26. for high in range(n-1, -1, -1): # range(n-1,0,-1)
  27. li[high], li[0] = li[0], li[high] # 1.退休 2.棋子
  28. sift(li, 0, high-1) # 3.调整
  29. li = list(range(100000))
  30. random.shuffle(li)
  31. heap_sort(li)

内置模块做堆

  1. import heapq
  2. import random
  3. # heap queue
  4. # priority queue 优先队列
  5. li = [9,5,8,4,7,6,3,2,1]
  6. heapq.heapify(li) # 小顶堆
  7. print(li)
  8. heapq.heappush(li, 1) # 给堆里添加值
  9. print(li)
  10. ele = heapq.heappop(li) # 从堆顶取值
  11. print(ele)
  12. print(li)
  13. # ele = heapq.heappop(li)
  14. # print(ele)
  15. # print(li)
  16. # 做堆排序
  17. heapq.heapify(li) # 建堆
  18. res = []
  19. while li:
  20. res.append(heapq.heappop(li))
  21. print(res)

归并排序

  • 假设现在的列表分两段有序,如何将其合成为一个有序列表
  1. import random
  2. from cal_time import cal_time
  3. def merge(li, low, mid, high):
  4. i = low # 左边的指针
  5. j = mid + 1 # 右边的指针
  6. li_tmp = []
  7. while i <= mid and j <= high: # 两边都有数
  8. if li[i] <= li[j]:
  9. li_tmp.append(li[i])
  10. i += 1
  11. else:
  12. li_tmp.append(li[j])
  13. j += 1
  14. # i<=mid 和 j<=high 两个条件 只能有一个满足
  15. while i <= mid:
  16. li_tmp.append(li[i])
  17. i += 1
  18. while j <= high:
  19. li_tmp.append(li[j])
  20. j += 1
  21. # li_tmp 0~high-low 复制回li low~high
  22. for i in range(len(li_tmp)):
  23. li[low+i] = li_tmp[i]
  24. def _merge_sort(li, low, high):
  25. if low < high: # 至少两个元素
  26. # print(li[low:high+1], '->', end=' ')
  27. mid = (low + high) // 2 # 分解
  28. # print(li[low:mid+1], li[mid+1: high+1])
  29. _merge_sort(li, low, mid) # 递归排序左边
  30. _merge_sort(li, mid+1, high) # 递归排序右边
  31. # print(li[low:mid+1], li[mid+1: high+1], '->', end=' ')
  32. merge(li, low, mid, high) # 一次归并 合并
  33. # print(li[low:high+1])
  34. @cal_time
  35. def merge_sort(li):
  36. _merge_sort(li, 0, len(li)-1)
  37. # li = [10,4,6,3,8,2,5,7]
  38. # merge_sort(li, 0, len(li)-1)
  39. # # print(li)
  40. # li = list(range(100000))
  41. # random.shuffle(li)
  42. # merge_sort(li)
  43. # li.sort()
  44. li = [
  45. {'age': 22, 'name':'abc'},
  46. {'age': 18, 'name':'qwe'},
  47. {'age': 22, 'name':'asd'},
  48. {'age': 26, 'name':'zxc'},
  49. {'age': 22, 'name':'tyu'},
  50. ]
  51. li.sort(key=lambda x:x['age'])
  52. print(li)

NB三人组-小结

  • 三种排序算法的时间复杂度都是

    • O(n log n)
  • 一般情况下,就运行时间而言:

    • 快速排序 < 归并排序 < 堆排序
  • 三种排序算法的缺点:

    • 快速排序:极端情况下排序效率低
    • 归并排序:需要额外的内存开销
    • 堆排序:在快的排序算法中相对较慢
排序方法 时间复杂度 空间复杂度 稳定性 代码复杂度
最坏情况 平均情况 最好情况
冒泡排序 O(n2) O(n2) O(n) O(1) 稳定 简单
直接选择排序 O(n2) O(n2) O(n2) O(1) 不稳定 简单
直接插入排序 O(n2) O(n2) O(n2) O(1) 稳定 简单
快速排序 O(n2) O(nlogn) O(nlogn) 平均情况O(logn); 最坏情况O(n) 不稳定 较复杂
堆排序 O(nlogn) O(nlogn) O(nlogn) O(1) 不稳定 复杂
归并排序 O(nlogn) O(nlogn) O(nlogn) O(n) 稳定 较复杂

快速排序 O(n logn) 堆排序 O(n logn) 归并排序 O(n logn)的更多相关文章

  1. 浅谈C++之冒泡排序、希尔排序、快速排序、插入排序、堆排序、基数排序性能对比分析之后续补充说明(有图有真相)

    如果你觉得我的有些话有点唐突,你不理解可以想看看前一篇<C++之冒泡排序.希尔排序.快速排序.插入排序.堆排序.基数排序性能对比分析>. 这几天闲着没事就写了一篇<C++之冒泡排序. ...

  2. 有k个list列表, 各个list列表的元素是有序的,将这k个列表元素进行排序( 基于堆排序的K路归并排序)

    解题思路: 排序方法:多路归并排序 每次将n个list的头元素取出来,进行排序(堆排序),最小元素从堆中取出后,将其所在list的下一个元素 放入堆中,调整堆序列. 函数实现原型: void list ...

  3. 整理C++面试题for非CS程序猿——更新至【48】

    结合网上的C++面试题+自己的面经,进行整理记录,for我这种非CS的程序猿.(不定期更新,加入了自己的理解,如有不对,请指出) [1] new/delete和malloc/free的区别和联系? 1 ...

  4. 寻找最大(小)的K个数

    <<编程之美>>一书中提到了寻找最大的K个数的问题,问题可以简单描述为:在长度为N的数组中,寻找第K(K<N)个最大的数.问题的解法涉及到了很多排序算法,对我们理解和运用 ...

  5. 数据结构 - 归并排序(merging sort)

    归并排序(merging sort): 包含2-路归并排序, 把数组拆分成两段, 使用递归, 将两个有序表合成一个新的有序表. 归并排序(merge sort)的时间复杂度是O(nlogn), 实际效 ...

  6. postgresql-分页数据重复问题探索

    postgresql-分页数据重复探索 问题背景 许多开发和测试人员都可能遇到过列表的数据翻下一页的时候显示了上一页的数据,也就是翻页会有重复的数据. 如何处理? 这个问题出现的原因是因为选择的排序字 ...

  7. postgresql-分页重复数据探索

    # postgresql-分页重复数据探索 ## 问题背景 许多开发和测试人员都可能遇到过列表的数据翻下一页的时候显示了上一页的数据,也就是翻页会有重复的数据. ### 如何处理? 这个问题出现的原因 ...

  8. 常见算法的python实现

    提到排序算法,常见的有如下几种:冒泡排序.选择排序.插入排序.快速排序.堆排序.归并排序.希尔排序:查找算法最常见二分查找.这些算法的时间复杂度如下: 算法名称 时间复杂度(一般情况) 冒泡排序 O( ...

  9. go实现堆排序、快速排序、桶排序算法

    一. 堆排序 堆排序是利用堆这种数据结构而设计的一种排序算法.以大堆为例利用堆顶记录的是最大关键字这一特性,每一轮取堆顶元素放入有序区,就类似选择排序每一轮选择一个最大值放入有序区,可以把堆排序看成是 ...

随机推荐

  1. springMVC_08文件上传

    一.步骤总结 导入jar包 配置web.xml 在src目录下创建配置文件mvc.xml 创建前段页面fileupload.jsp 创建controller类HelloController 配置mvc ...

  2. [转] 快速部署Tomcat项目的Shell脚本

    为了做集群测试,在每台机器上装了3个tomcat,每次发布项目的时候都要反复敲一些命令,重启tomcat之前先检查tomcat进程有没有停掉,没有还要手动kill该进程. 发布次数多了,操作就比较繁琐 ...

  3. Java基础-一文搞懂位运算

    在日常的Java开发中,位运算使用的不多,使用的更多的是算数运算(+.-.*./.%).关系运算(<.>.<=.>=.==.!=)和逻辑运算(&&.||.!), ...

  4. 8张图让你一步步看清 async/await 和 promise 的执行顺序

    摘要: 面试必问 原文:8张图帮你一步步看清 async/await 和 promise 的执行顺序 作者:ziwei3749 Fundebug经授权转载,版权归原作者所有. 为什么写这篇文章? 说实 ...

  5. Codeforces617E(莫队)

    E. XOR and Favorite Number time limit per test: 4 seconds memory limit per test: 256 megabytes input ...

  6. @Value取不到值的原因(引用application.properties中自定义的值)

    在spring mvc架构中,如果希望在程序中直接使用properties中定义的配置值,通常使用一下方式来获取: @Value("${tag}") private String ...

  7. BZOJ4805: 欧拉函数求和(杜教筛)

    4805: 欧拉函数求和 Time Limit: 15 Sec  Memory Limit: 256 MBSubmit: 614  Solved: 342[Submit][Status][Discus ...

  8. 如何用ABP框架快速完成项目(10) - ABP只要加人即可马上加快项目进展- 全栈篇(1) - 发挥DDD理论优势的时候到了!

    正如我在<程序员英语二三事(2) - 从听开始>里说的, 任何技术/工具/语言都有其适用场景和上下文环境. DDD理论同样是如此.   现在, 终于到了发挥DDD理论优势的时候啦!   一 ...

  9. SQL注入与防范

    首先给大家看个例子: 1)小编首先在数据库中建立了一张测试表logintable,表内有一条测试信息: 然后写了个测试程序: package com.java.SqlInject; import ja ...

  10. C#字典Dictionay多线程读是否是安全的

    答案:是线程安全的,只读不写多线程下,完全不需要加锁! 测试代码: using System; using System.Diagnostics; using System.Threading; us ...