冒泡排序(bubble sort)

思路

以升序为例:

从第一个数开始向后两两对比,将大的数一直向后移动,直至最大的数移到最后,再找第二大的数

最好情况:O(n)

一般情况:O(n^2)

最坏情况:O(n^2)

代码

import random

def bubble_sort(l):
for i in range(len(l) - 1):
exchange = False
for j in range(len(l) - 1 - i):
if l[j] > l[j + 1]:
l[j], l[j + 1] = l[j + 1], l[j]
exchange = True
if not exchange: # 如果一次循环中都没有交换,则说明已经排序完成,可以提前结束
break if __name__ == '__main__':
data = list(range(1000))
random.shuffle(data)
bubble_sort(data)
print(data)

选择排序(selection sort)

思路

以升序为例:

从第一个位置开始向后寻找,找到最小的数,放在这个位置,之后向后移一个位置

时间复杂度

最好情况:O(n^2)

一般情况:O(n^2)

最坏情况:O(n^2)

代码

import random

def selection_sort(l):
for i in range(len(l) - 1):
min_num = i
for j in range(i + 1, len(l)):
if l[j] < l[min_num]:
min_num = j
if min_num != i:
l[i], l[min_num] = l[min_num], l[i] if __name__ == '__main__':
data = list(range(1000))
random.shuffle(data)
selection_sort(data)
print(data)

插入排序(insertion sort)

思路

以升序为例:

将第一个数分为有序队列,后面为无序队列。从二个数开始,依次插入前面有序队列

时间复杂度

最好情况:O(n)

一般情况:O(n^2)

最坏情况:O(n^2)

代码

import random

def insertion_sort(l):
for i in range(1, len(l)):
tem = l[i]
j = i - 1
while j >= 0 and tem < l[j]:
l[j + 1] = l[j]
j -= 1
l[j + 1] = tem if __name__ == '__main__':
data = list(range(1000))
random.shuffle(data)
insertion_sort(data)
print(data)

快速排序(quicksort)

Python 的 sort 时间复杂度为 O(nlogn),但是因为是 C 写的,所以会快

思路

以升序为例:

从第一个数开始,将其他数分成两部分,小于这个数的放在左边,大于这个数的放在右边,分出的左右两边分别继续执行。

时间复杂度

最好情况:O(nlogn)

一般情况:O(nlogn)

最坏情况:O(n^2)

代码

import random

def quick_sort(l, left, right):
if left < right:
mid = partition(l, left, right)
quick_sort(l, left, mid - 1)
quick_sort(l, mid + 1, right) def partition(l, left, right):
tem = l[left]
while left < right:
# 一次循环左右各移动一位
while left < right and l[right] > tem:
# 当前位不需要换位置,指针向内移动一位,直至遇到需要换位置的位
right -= 1
l[left] = l[right] # 将右边需要换位置的换到左边(取出的数之前的位置)
while left < right and l[left] < tem:
left += 1
l[right] = l[left]
l[left] = tem
return left if __name__ == '__main__':
data = list(range(1000))
random.shuffle(data)
quick_sort(data, 0, len(data) - 1)
print(data)

堆排序(heapsort)

思路

以升序为例:

借助最大堆(大根堆)的特性,依次取出堆中最大的数(根结点的数),再对堆进行调整

时间复杂度

最好情况:O(nlogn)

一般情况:O(nlogn)

最坏情况:O(nlogn)

代码

import random

def sift(l, low, high):
i = low # 指向父节点
j = 2 * i + 1 # 指向左节点
tem = l[i] # 获取父节点的值
while j <= high: # 如果子节点在堆中(有子节点)
if j < high and l[j] < l[j + 1]: # 有右节点且比左节点大
j += 1 # 指向右节点
if tem < l[j]: # 如果根结点小于子节点中较大的那个
l[i] = l[j] # 将较大的值放入父节点
i = j # 指向下一层树
j = 2 * i + 1
else:
break
l[i] = tem # 将循环开始时的父节点数据写入 def heap_sort(l):
n = len(l)
for i in range(n // 2 - 1, -1, -1):
sift(l, i, n - 1)
# 堆建好了
for i in range(n - 1, -1, -1): # i 指向堆堆最后
l[0], l[i] = l[i], l[0] # 将当前最大数移到最后,最后的数移到根结点
sift(l, 0, i - 1) if __name__ == '__main__':
data = list(range(1000))
random.shuffle(data)
heap_sort(data)
print(data)

归并排序(merge sort)

思路

以升序为例:

由于将两个有序列表合并比较简单,所以将列表无限分割成仅有一个元素的有序列表,之后再合并

时间复杂度

最好情况:O(nlogn)

一般情况:O(nlogn)

最坏情况:O(nlogn)

代码

import random

def merge_sort(l, low, high):
if low < high:
mid = (low + high) // 2
merge_sort(l, low, mid) # 前半部分迭代
merge_sort(l, mid + 1, high) # 后半部分迭代
merge(l, low, mid, high) # 调整 def merge(l, low, mid, high):
"""
用于将两个有序列表进行合并
"""
i = low # 指向左边有序列表第一个元素
j = mid + 1 # 指向右边有序列表第一个元素
tem_l = [] # 临时列表,用于存放合并后列表
while i <= mid and j <= high:
# 当左右列表中都有元素时
if l[i] <= l[j]:
tem_l.append(l[i])
i += 1
else:
tem_l.append(l[j])
j += 1
while i <= mid:
# 当左边列表中有元素时,直接将剩下的元素全部插入临时列表
tem_l.append(l[i])
i += 1
while j <= high:
# 当右边列表中有元素时,直接将剩下的元素全部插入临时列表
tem_l.append(l[j])
j += 1
# 用排序完成的元素替代未排序的元素
l[low:high + 1] = tem_l if __name__ == '__main__':
data = list(range(1000))
random.shuffle(data)
merge_sort(data, 0, len(data) - 1)
print(data)

希尔排序(Shell's sort)

思路

以升序为例:

将元素分为n组,每一组进行插入排序,再将每组元素增加直至所有元素都在一组中

时间复杂度

O((1 + τ)n)

一般情况:O(1.3n)

代码

import random

def shell_sort(l):
gap = len(l) // 2
while gap > 0:
for i in range(gap, len(l)):
tem = l[i]
j = i - gap # 指向同组前一个元素
while j >= 0 and tem < l[j]: # 存在前一个元素并且比当前元素大
l[j + gap] = l[j] # 将前一个元素移到后面一位
j -= gap # 指向前一个元素
l[j + gap] = tem
gap //= 2 if __name__ == '__main__':
data = list(range(1000))
random.shuffle(data)
shell_sort(data)
print(data)

Python 基础排序算法的更多相关文章

  1. python常见排序算法解析

    python——常见排序算法解析   算法是程序员的灵魂. 下面的博文是我整理的感觉还不错的算法实现 原理的理解是最重要的,我会常回来看看,并坚持每天刷leetcode 本篇主要实现九(八)大排序算法 ...

  2. python 经典排序算法

    python 经典排序算法 排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存.常见的内部排序算 ...

  3. Java面试宝典系列之基础排序算法

    本文就是介绍一些常见的排序算法.排序是一个非常常见的应用场景,很多时候,我们需要根据自己需要排序的数据类型,来自定义排序算法,但是,在这里,我们只介绍这些基础排序算法,包括:插入排序.选择排序.冒泡排 ...

  4. php四种基础排序算法的运行时间比较

    /** * php四种基础排序算法的运行时间比较 * @authors Jesse (jesse152@163.com) * @date 2016-08-11 07:12:14 */ //冒泡排序法 ...

  5. Python之排序算法:快速排序与冒泡排序

    Python之排序算法:快速排序与冒泡排序 转载请注明源地址:http://www.cnblogs.com/funnyzpc/p/7828610.html 入坑(简称IT)这一行也有些年头了,但自老师 ...

  6. python实现排序算法 时间复杂度、稳定性分析 冒泡排序、选择排序、插入排序、希尔排序

    说到排序算法,就不得不提时间复杂度和稳定性! 其实一直对稳定性不是很理解,今天研究python实现排序算法的时候突然有了新的体会,一定要记录下来 稳定性: 稳定性指的是 当排序碰到两个相等数的时候,他 ...

  7. Java基础系列--基础排序算法

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9082138.html 一.概述 基础排序算法包括:桶排序.冒泡排序.选择排序.插入排序等 ...

  8. 6种基础排序算法java源码+图文解析[面试宝典]

    一.概述 作为一个合格的程序员,算法是必备技能,特此总结6大基础算法.java版强烈推荐<算法第四版>非常适合入手,所有算法网上可以找到源码下载. PS:本文讲解算法分三步:1.思想2.图 ...

  9. 第四百一十五节,python常用排序算法学习

    第四百一十五节,python常用排序算法学习 常用排序 名称 复杂度 说明 备注 冒泡排序Bubble Sort O(N*N) 将待排序的元素看作是竖着排列的“气泡”,较小的元素比较轻,从而要往上浮 ...

随机推荐

  1. vscode笔记

    一.修改操作栏字体 https://www.cnblogs.com/liuyangfirst/p/9759966.html 1.代码改写,进入默认安装的如下路径,搜索workbench 2.用Vs c ...

  2. ACWING 95 费解的开关 解题记录

    你玩过“拉灯”游戏吗?25盏灯排成一个5x5的方形.每一个灯都有一个开关,游戏者可以改变它的状态.每一步,游戏者可以改变某一个灯的状态.游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也 ...

  3. JVM的类加载过程以及双亲委派模型详解

    JVM的类加载过程以及双亲委派模型详解 这篇文章主要介绍了JVM的类加载过程以及双亲委派模型详解,类加载器就是根据指定全限定名称将 class 文件加载到 JVM 内存,然后再转化为 class 对象 ...

  4. JavaWeb 增删改查功能

    1.今天来写一个简单的增删改查功能,这个项目还是接着在昨天写的 --JavaWeb实现简单登录注册-- 来写的. 登录成功进来后对学生信息的增删改查 2.项目文件为: 3.好了,直接贴上今天新写的代码 ...

  5. 图解Java常用数据结构

    最近在整理数据结构方面的知识, 系统化看了下 Java 中常用数据结构, 突发奇想用动画来绘制数据流转过程. 主要基于 jdk8, 可能会有些特性与 jdk7 之前不相同, 例如 LinkedList ...

  6. nodejs环境下的socket通信

    结构: socket是应用层和传输层的桥梁.(传输层之上的协议所涉及的数据都是在本机处理的,并没进入网络中) 涉及数据: socket所涉及的数据是报文,是明文. 作用: 建立长久链接,供网络上的两个 ...

  7. java高并发系列 - 第10天:线程安全和synchronized关键字

    这是并发系列第10篇文章. 什么是线程安全? 当多个线程去访问同一个类(对象或方法)的时候,该类都能表现出正常的行为(与自己预想的结果一致),那我们就可以所这个类是线程安全的. 看一段代码: pack ...

  8. Java开发桌面程序学习(八)——启动浏览器或者打开资源管理器操作与hyperlink超链接的使用

    启动浏览器或者打开资源管理器 启动浏览器 java1.6版本以上,Desktop Desktop.getDesktop().browse(new URI("www.cnblogs.com/k ...

  9. c#中取绝对值

    记一次工作中查询的资料: System.Math.Abs(float value); System.Math.Abs(decimal value); System.Math.Abs(int value ...

  10. C# WinForm实现禁止最大化、最小化、双击标题栏、双击图标等操作

    protected override void WndProc(ref Message m) { if (m.Msg==0x112) { switch ((int) m.WParam) { //禁止双 ...