归并排序

使用分治法:分而治之

分:

  • 递归地拆分数组,直到它被分成两对单个元素数组为止.
  • 然后,将这些单个元素中的每一个与它的对合并,然后将这些对与它们的对等合并,直到整个列表按照排序顺序合并为止.

治:

  • 将2个排序列表合并为另一个排序列表是很简单的.
  • 简单地通过比较每个列表的头,删除最小的,以加入新排序的列表.
  • O(n) 操作

图示:

动图:

实现

# 合并
def merge(a, b):
c = []
while len(a) > 0 and len(b) > 0:
if a[0] < b[0]:
c.append(a[0])
a.remove(a[0])
else:
c.append(b[0])
b.remove(b[0]) if len(a) == 0:
c += b
else:
c += a
return c # 排序
def merge_sort(li):
if len(li) <= 1:
return li
# 整除2
m = len(li) // 2
a = merge_sort(li[:m])
b = merge_sort(li[m:])
return merge(a, b)

算法分析

  • 平均时间复杂度:O(nlog2n)
  • 最好时间复杂度:O(nlog2n)
  • 最坏时间复杂度:O(nlog2n)
  • 空间复杂度:O(n)
  • 稳定性:稳定的

快速排序

从数列中挑出一个元素,称为 “基准”(pivot);

重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。

在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;

递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;

实现

简易版

# 快速排序1
def quick_sort_one(li):
if len(li) <= 1:
return li
v = li[0]
left = quick_sort_one([i for i in li[1:] if i <= v])
right = quick_sort_one([i for i in li[1:] if i > v])
return left + [v] + right

partition分区

import random

def quick_sort(li, left, right):
if left < right: # 待排序的区域至少有两个元素
mid = partition(li, left, right)
quick_sort(li, left, mid - 1)
quick_sort(li, mid + 1, right) # partition分区
def partition(li, left, right):
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
return left li = list(range(100))
random.shuffle(li) quick_sort(li, 0, len(li) - 1)
print(li)

算法分析

  • 平均时间复杂度:O(nlog2n)
  • 最好时间复杂度:O(nlog2n)
  • 最坏时间复杂度:O(n2)
  • 空间复杂度:O(nlog2n)
  • 稳定性:不稳定的

堆排序

  1. 建立堆
  2. 得到堆顶元素,为最大元素
  3. 去掉堆顶,将堆最后一个元素放到堆顶,此时可通过一次调整重新使对有序
  4. 堆顶元素为第二大元素
  5. 重复步骤3,直到堆为空,排序结束

实现

import random

def sift(li, low, high):
# li表示树, low表示树根, high表示树最后一个节点的位置
tmp = li[low]
i = low
j = 2 * i + 1 # 初识j指向空位的左孩子
# i指向空位,j指向两个孩子
while j <= high: # 循环退出的第二种情况: j>high,说明空位i是叶子节点
if j + 1 <= high and li[j] < li[j + 1]: # 如果右孩子存在并且比左孩子大,指向右孩子
j += 1
if li[j] > tmp:
li[i] = li[j]
i = j
j = 2 * i + 1
else: # 循环退出的第一种情况:j位置的值比tmp小,说明两个孩子都比tmp小
break
li[i] = tmp def heap_sort(li):
n = len(li)
# 1. 构造堆
for low in range(n // 2 - 1, -1, -1):
sift(li, low, n - 1)
# 2. 挨个出数
for high in range(n - 1, -1, -1):
li[0], li[high] = li[high], li[0] # 退出 棋子
sift(li, 0, high - 1) li = list(range(100))
random.shuffle(li)
heap_sort(li)
print(li)

算法分析

  • 平均时间复杂度:O(nlog2n)
  • 最好时间复杂度:O(nlog2n)
  • 最坏时间复杂度:O(nlog2n)
  • 空间复杂度:O(1)
  • 稳定性:不稳定的

~>.<~

使用python实现归并排序、快速排序、堆排序的更多相关文章

  1. Python与Go快速排序

    #!/usr/bin/env python # -*- coding: utf-8 -*- # 快速排序 # 时间复杂度 O(n lgn)-- O(n^2) def quick_sort(array) ...

  2. python实现归并排序,归并排序的详细分析

    python实现归并排序,归并排序的详细分析.   学习归并排序的过程是十分痛苦的.它并不常用,看起来时间复杂度好像是几种排序中最低的,比快排的时间复杂度还要低,但是它的执行速度不是最快的.很多朋友不 ...

  3. 插入排序、冒泡排序、选择排序、希尔排序、高速排序、归并排序、堆排序和LST基数排序——C++实现

    首先是算法实现文件Sort.h.代码例如以下: <pre name="code" class="java">/* * 实现了八个经常使用的排序算法: ...

  4. Python入门篇-数据结构堆排序Heap Sort

    Python入门篇-数据结构堆排序Heap Sort 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.堆Heap 堆是一个完全二叉树 每个非叶子结点都要大于或者等于其左右孩子结点 ...

  5. 四、归并排序 && 快速排序

    一.归并排序 Merge Sort 1.1.实现原理 如果要排序一个数组,我们先把数组从中间分成前后两部分,然后对前后两部分分别排序,再将排好序的两部分合并在一起,这样整个数组就都有序了. 归并排序使 ...

  6. Python实现八大排序(基数排序、归并排序、堆排序、简单选择排序、直接插入排序、希尔排序、快速排序、冒泡排序)

    目录 八大排序 基数排序 归并排序 堆排序 简单选择排序 直接插入排序 希尔排序 快速排序 冒泡排序 时间测试 八大排序 大概了解了一下八大排序,发现排序方法的难易程度相差很多,相应的,他们计算同一列 ...

  7. Javascript中的冒泡排序,插入排序,选择排序,快速排序,归并排序,堆排序 算法性能分析

    阿里面试中有一道题是这样的: 请用JavaScript语言实现 sort 排序函数,要求:sort([5, 100, 6, 3, -12]) // 返回 [-12, 3, 5, 6, 100],如果你 ...

  8. 高速排序,归并排序,堆排序python实现

    高速排序的时间复杂度最好情况下为O(n*logn),最坏情况下为O(n^2),平均情况下为O(n*logn),是不稳定的排序 归并排序的时间复杂度最好情况下为O(n*logn),最坏情况下为O(n*l ...

  9. 牛B三人组-快速排序-堆排序-归并排序

    快速排序 随便取个数,作为标志值,这里就默认为索引位置为0的值 记录左索引和右索引,从右往左找比标志值小的,小值和左索引值交换,右索引变化,然后从左往右找比标志值大的,大值和右索引值交换,左索引变化 ...

随机推荐

  1. eclipse debug启动时tomcat报错

    Class.getDeclaredConstructors0(boolean) line: not available [native method] tomcat  debug启动突然启动不起来 停 ...

  2. http断点续传的原理

    ——————————————先讲原理,如下:—————————————————— 举一个详细的例子: 一般场景,要访问的域名:www.jizhuomi.com/android,文件名为down.zip ...

  3. 转载:reverb

    https://blog.csdn.net/qiumingjian/article/details/43938687 https://blog.csdn.net/jsjwangmingmin/arti ...

  4. 【Python】 数字求和

    # 用户输入数字 num1 = input('输入第一个数字:') num2 = input('输入第二个数字:') # 求和 sum = float(num1) + float(num2) # 显示 ...

  5. python2.7 字符处理小节

    unicode是字符集 utf-8,gbk是编码方式,将字符集编码为机器识别的字节码 #encoding: utf-8 s = "中文" #unicode的utf-8编码,\xE4 ...

  6. PAT-链表-A1032 Sharing

    题意:给出两条链表的首地址以及若干个节点的的地址.数据.下一个节点的地址,求两条链表的首个共用节点的地址.如果两条链表没有共用节点,则输出-1. 思路:使用静态链表,首先遍历一遍第一个链表并进行标记. ...

  7. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"/>

    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1, ...

  8. Abp.Core运行时提示XX没有实现,或者没有依赖注入的问题,或者调试时提示做出更改的问题

    因为abp的web层对application层有项目引用,但是对domain层并不存在项目引用,而是bin目录下直接引用的dll文件,所以当domain层修改后不会自动将dll文件同步过去.所以有时候 ...

  9. kuangbin专题 专题九 连通图 Critical Links UVA - 796

    题目链接:https://vjudge.net/problem/UVA-796 题目:裸的求桥,按第一个元素升序输出即可. #include <iostream> #include < ...

  10. 详解多线程MT和多线程MD的区别

    这段时间司在招实习生,而不管是远程的电话面试或者是实际现场面试中领导都喜欢问你这个问题,但是可惜的是能很好答上来的人很少.后来发现不管是应届的实习生,甚至有些实际参加工作几年的人也未必真的了解这个问题 ...