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. echarts地图 禁止高亮显示(转载)

    转载来源: https://blog.csdn.net/john1337/article/details/54666759 案例一:在实际应用中希望(没有数据的省会)禁止高亮颜色,解决方案: mapC ...

  2. [android] 采用服务录制电话&服务的生命周期

    根据上一节代码里,加入一个录音功能,上传到服务器,就能实现一个录制器 当手机处于通话状态时,开启录音机 获取MediaRecorder对象,通过new出来 调用MediaRecorder对象的setA ...

  3. mysql中union 查询

    UNION ALL只是简单的将两个结果合并后就返回.这样,如果返回的两个结果集中有重复的数据,那么返回的结果集就会包含重复的数据了. 从效率上说,UNION ALL 要比UNION快很多,所以,如果可 ...

  4. 【Java每日一题】20170313

    20170310问题解析请点击今日问题下方的“[Java每日一题]20170313”查看(问题解析在公众号首发,公众号ID:weknow619) package Mar2017; import jav ...

  5. JSJ—案例谈面向对象

    有人告诉我那里遍地都是对象——我们把所有的程序代码放在main()里面,事实上,那根本就不是面向对象的做法,在Java的面向对象中,我们也会看到类和对象的不同,以及对象是如何让你的生活更美好(至少程序 ...

  6. Mac包管理神器Homebrew

    概念 简称brew,是Mac OSX上的软件包管理工具,能在Mac中方便的安装软件或者卸载软件,相当于Red hat的yum.Ubuntu的apt-get. 安装命令 ruby -e "$( ...

  7. 中文代码示例之Electron桌面应用开发初体验

    参考: 打造你的第一个 Electron 应用 首先运行下面在目录下创建package.json: $ npm init 去掉了一些无关项后内容如下: { "name": &quo ...

  8. input的type类型

    对部分生僻的input属性值解释: type="reset": 可以一键清空form表单里面所有的数据 <form> <input type="text ...

  9. Salesforce 数据备份和恢复小知识

    数据备份的类型 在Salesforce中可以使用多种API进行数据备份,它们是: REST API SOAP API Buik API Metadata API 数据备份有三种选择: 完全备份(Ful ...

  10. wap2app(二)-- 设置APP系统状态栏

    准备 工具:HBuilder 一.全屏设置,不显示系统状态栏 这里所说的系统状态栏就是包括了:信号.运营商.电量等信息手机屏幕最顶部信息. 全屏并非状态栏透明或变色,而是没有状态栏,也就是看不见电量. ...