NB三人组

快速排序

  • 思路"

    • 取一个元素P (第一个元素), 使元素归位
    • 列表被P 分成两部分,左边都比P小,右边比P大;
    • 递归完成排序.
  • 问题 如果是已经排序好的 倒叙 列表 则会 递归深度越界
    • 每次
# 时间复杂度: O(n*logn)
import sys
import random
from cal_time import cal_time
# 设置递归深度
sys.setrecursionlimit(10000) def _quick_sort(li, left, right):
if left < right: # 递归区域至少有两个元素
# 归位 [left, right] --> [left, mid-1] [mid+1, right]
mid = partition(li, left, right)
_quick_sort(li, left, mid-1)
_quick_sort(li, mid+1, right) @cal_time
def quick_sort(li):
_quick_sort(li, 0, len(li)-1) def partition(li, left, right):
# 解决最坏情况
# i = random.randint(left, right)
# li[i], li[left] = li[left], li[i]
tmp = li[left]
while left < right:
while left < right and li[right] >= tmp:
right -= 1
li[left] = li[right]
while left < right and li[left] <= tmp:
left += 1
li[right] = li[left]
li[left] = tmp # 此时 left = right
return left def gogogo2(li, left, right):
# 区域1:[left, i] 区域2:[i+1, j-1]
i = left - 1 # 初识区域1和区域2都空
for j in range(left, right):
if li[j] < li[right]: # 归到区域1
i += 1
li[j], li[i] = li[i], li[j]
li[right], li[i+1] = li[i+1], li[right]
return i+1 @cal_time
def quick_sort2(li):
return _quick_sort2(li) def _quick_sort2(li):
if len(li) < 2:
return li
x = li[0]
left = [li[i] for i in range(1, len(li)) if li[i] <= x]
right = [li[i] for i in range(1, len(li)) if li[i] > x]
_quick_sort2(left)
_quick_sort2(right)
return left + [x] + right # @cal_time
# def sys_sort(li):
# li.sort() import copy li = list(range(10000))
random.shuffle(li)
li2 = copy.copy(li) quick_sort(li)
quick_sort2(li2) # sys_sort(li) # 另类写法 def my_partition(li, l, r):
a = li[l]
i = l + 1
while i <= r:
if li[i] >= a:
li[r], li[i] = li[i], li[r]
r -= 1
else:
i += 1
li[i - 1], li[l] = li[l], li[i - 1]
return i def quick_sort(li, left, right):
if left < right:
tmp = my_partition(li, left, right)
quick_sort(li, left, tmp -1)
quick_sort(li, tmp, right) @cal_time
def _quick_sort(li):
quick_sort(li, 0, len(li) - 1)

堆排序

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

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

内置模块做堆

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

归并排序

  • 假设现在的列表分两段有序,如何将其合成为一个有序列表
import random
from cal_time import cal_time def merge(li, low, mid, high):
i = low # 左边的指针
j = mid + 1 # 右边的指针
li_tmp = []
while i <= mid and j <= high: # 两边都有数
if li[i] <= li[j]:
li_tmp.append(li[i])
i += 1
else:
li_tmp.append(li[j])
j += 1
# i<=mid 和 j<=high 两个条件 只能有一个满足
while i <= mid:
li_tmp.append(li[i])
i += 1
while j <= high:
li_tmp.append(li[j])
j += 1
# li_tmp 0~high-low 复制回li low~high
for i in range(len(li_tmp)):
li[low+i] = li_tmp[i] def _merge_sort(li, low, high):
if low < high: # 至少两个元素
# print(li[low:high+1], '->', end=' ')
mid = (low + high) // 2 # 分解
# print(li[low:mid+1], li[mid+1: high+1])
_merge_sort(li, low, mid) # 递归排序左边
_merge_sort(li, mid+1, high) # 递归排序右边
# print(li[low:mid+1], li[mid+1: high+1], '->', end=' ')
merge(li, low, mid, high) # 一次归并 合并
# print(li[low:high+1]) @cal_time
def merge_sort(li):
_merge_sort(li, 0, len(li)-1) # li = [10,4,6,3,8,2,5,7]
# merge_sort(li, 0, len(li)-1)
# # print(li) # li = list(range(100000))
# random.shuffle(li)
# merge_sort(li) # li.sort() li = [
{'age': 22, 'name':'abc'},
{'age': 18, 'name':'qwe'},
{'age': 22, 'name':'asd'},
{'age': 26, 'name':'zxc'},
{'age': 22, 'name':'tyu'},
]
li.sort(key=lambda x:x['age'])
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. WebAPI参数传值string转bool,int转bool相关问题

    今天在公司同事问了我一个问题,用postman传递json字符串给接口,接口获取到的值不正确. 我就看到下面的json数据: { "Mark":"1" } 接口 ...

  2. virtualbox中 清理磁盘

    1. 碎片整理 windows: 下载 sdelete 工具 执行命令: sdelete –z c:\ Linux: 执行如下命令: sudo dd if=/dev/zero of=/EMPTY bs ...

  3. Laravel5.5 数据库迁移:创建表与修改表

    数据库迁移是数据库的版本管理,要使用数据库迁移,需要在.env文件中连接好数据库(不多说).laravel本身已经存在user表和password_resets表的迁移了,因此,执行 php arti ...

  4. blfs(systemd版本)学习笔记-为桌面环境构建xorg服务

    我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! lfs准备使用桌面环境,首先需要构建xorg服务 xorg服务项目地址:http://www.linuxfromscratch. ...

  5. 洛谷P3246 [HNOI2016]序列(离线 差分 树状数组)

    题意 题目链接 Sol 好像搞出了一个和题解不一样的做法(然而我考场上没写出来还是爆零0) 一个很显然的思路是考虑每个最小值的贡献. 预处理出每个数左边第一个比他小的数,右边第一个比他大的数. 那么\ ...

  6. Python中字典dict

    dict字典 字典是一种组合数据,没有顺序的组合数据,数据以键值对形式出现 # 字典的创建 # 创建空字典1 d = {} print(d) # 创建空字典2 d = dict() print(d) ...

  7. 用ABP只要加人即可马上加快项目进展(二) - 分工篇

    2018年和1998年其中两大区别就是: 前端蓬勃发展, 前后端分离是一个十分大的趋势. 专门的测试人员角色被取消, 多出了一个很重要的角色, 产品经理   ABP只要加入即可马上加快项目进展, 选择 ...

  8. ionic提示弹框

    //提示框 .factory('TipsPort', function ($ionicPopup) { var TipsPort = function (tipsText, SureFunction, ...

  9. H264-YUV通过RTP接收视频流ffmpeg解码SDL实时播放

    写在前面的话 写一个简单的播放器,通过RTP接收视频流,进行实时播放.最初,使用ffplay或者vlc接收按照SDP协议文件可以播放视频,但是视频中断后重启,不能正确的解包,时常会出现如下的错误信息. ...

  10. codeforces 2B The least round way(DP+数学)

    The least round way 题目链接:http://codeforces.com/contest/2/problem/B ——每天在线,欢迎留言谈论.PS.本题有什么想法.建议.疑问 欢迎 ...