若干排序算法的Python实现方法及原理
今天突然想到了一个问题:让你立即把堆排、快排等等排序算法写出来会不会,并且不能犯逻辑错误?
我说:不会,至少需要思考一下,并且可能还需要时间调试。
之前总是觉得,不就是排序算法吗?有什么大不了的?网上、书上一查一大堆。但是换个角度想:1+1 = ? 你会不会?
排序算法应是作为最基本的工具一样,是信手捏来的,所以我把《算法导论》上的几个排序问题看了并且实现了一遍;在此做分享:
冒泡排序:
冒泡排序应该算是比较简单并且使用广泛的排序算法之一了吧,但是它的效率并不怎么高,我们可以先看一下实现:
def bubbleSort(A):
length = len(A);
for i in range(0, length):
for j in range(length - 1, i, -1):
if A[j] < A[j - 1]:
(A[j], A[j - 1]) = (A[j - 1], A[j]);
return A;
a = [5, 0, 1, 3, 6, 2, 4, 9, 12, 11, 18, 20, 7, 8, 19, 13, 14, 17, 16, 10];
a = bubbleSort(a);
print(a);
顾名思义,冒泡排序就像泡沫一样一层一层往上冒,需要一个一个比较;
比较次数(n-1)n / 2, 数据交换次数最坏情况3(n-1)*n/2,最好情况0,所以其时间复杂度O(n^2);
插入排序:
def insertionSort(A):
for i in range(1, len(A)):
key = A[i];
j = i - 1;
while (j >= 0) and (A[j] > key):
A[j + 1] = A[j];
j = j - 1;
A[j+1] = key;
return A;
a = [5, 0, 1, 3, 6, 2, 4, 9, 12, 11, 18, 20, 7, 8, 19, 13, 14, 17, 16, 10];
a = insertionSort(a);
print(a);
要理解插入排序,可以想象打扑克的时候是怎么拿牌的,我们摸一张牌,然后从左往右(或从右往左)按顺序比较,再把牌插入相应位置,插入排序就是这种思想。
时间复杂度O(n^2)
归并排序:
记得大二学习《数据结构》第一次写这个算法的时候想了好久,因为使用递归的思想,有些地方总是转不过弯来。
def merge(A):
length = len(A);
if length <= 1 : return A;
n1 = length / 2;
n2 = length - n1;
L = [];
R = [];
for i in range(0, n1):
L.append(A[i]);
for i in range(0, n2):
R.append(A[n1 + i]);
if n1 > 1 : merge(L);
if n2 > 1 : merge(R);
i = 0;
j = 0;
for k in range(0, length):
if L[i] < R[j]:
A[k] = L[i];
i = i + 1;
if i >= n1:
for i in range(j, n2):
k = k + 1;
A[k] = R[i];
break;
else:
A[k] = R[j]
j = j + 1;
if j >= n2:
for j in range(i, n1):
k = k + 1;
A[k] = L[j];
break;
return A;
a = [5, 0, 1, 3, 6, 2, 4, 9, 12, 11, 18, 20, 7, 8, 19, 13, 14, 17, 16, 10];
a = merge(a);
print(a);
如果你能很好的理解递归的思想的话,想必归并排序也是很简单的。其核心思想在于怎么把问题分解成一系列类型一样的小问题。我们可以这样想:
两个排好序的数列怎么合并成一个序列?
两个序列的数据一个一个比较,将小的存入新的队列,直至这两个数列一个为空,则将另外一个数列剩余数据插入队列。如果你把这两个数列想象成扑克的话或许更好理解。如果这两个序列都只有一个数据的话,是不是会很简单的就排完了?
[1, 3, 5], [2, 4, 6, 7] ======> [1, 2, 3, 4, 5, 6, 7]
归并排序通过递归方法,最终将一个待排序序列换成若干组待排序的包含一个数据的数列。
时间复杂度O(nlog(n))
堆排序:
曾经,第一次写堆排,用C链表,自信满满地构建了一颗二叉树!原来堆排序不需要构建一颗视觉上的二叉树!!!运用原址排序(只操作下标和对应的元素)解决!!!
parent = lambda i : (i - 1) / 2;
left = lambda i : 2 * i + 1;
right = lambda i : 2 * i + 2;
exchange = lambda a, b : (b, a);
def maxHeapfy(A, i, length):
l = left(i);
r = right(i);
if l < length and A[l] > A[i]:
large = l;
else:
large = i;
if r < length and A[r] > A[large]:
large = r;
if large != i:
(A[i], A[large]) = exchange(A[i], A[large]);
maxHeapfy(A, large, length);
return A;
def buildHeap(A, length):
for i in range(length / 2 - 1, -1, -1):
maxHeapfy(A, i, length);
def heapSort(A):
length = len(A);
buildHeap(A, length);
for i in range(len(A) - 1, 0, -1):
(A[0], A[i]) = exchange(A[0], A[i]);
length = length - 1;
maxHeapfy(A, 0, length);
return A;
a = [5, 0, 1, 3, 6, 2, 4, 9, 12, 11, 18, 20, 7, 8, 19, 13, 14, 17, 16, 10];
a = heapSort(a);
print(a);
堆排的思想在于理解最大(小)堆的概念:对于一个二叉树,父节点总是不小(大)于子节点的,即
A[parent(i)] >= A[i] ......①
后面便于称述不过于冗余,只讨论最大堆。
所以堆排的第一目的是建立一个满足条件的最大堆,要建立最大堆,就需要有最大堆的判定条件,即①式。建立最大堆之后,将根节点找到、保存并剔除、对剩下的序列继续做最大堆,重复上述过程即可完成排序。
时间复杂度O(nlog(n))
快速排序:
注意也是原址排序!!!
def partition(A, p, r):
x = A[r];
i = p - 1;
for j in range(p, r):
if A[j] <= x:
i = i + 1;
(A[i], A[j]) = (A[j], A[i]);
(A[i + 1], A[r]) = (A[r], A[i + 1]);
return i + 1;
def quickSort(A, p, r):
if p < r:
q = partition(A, p, r);
quickSort(A, p, q - 1);
quickSort(A, q + 1, r);
return A;
a = [5, 0, 1, 3, 6, 2, 4, 9, 12, 11, 18, 20, 7, 8, 19, 13, 14, 17, 16, 10];
a = quickSort(a, 0, len(a) - 1);
print(a);
快排的思想在于将序列分成三部分A[0,i-1],A[i],A[i+1,n],并且满足条件A[0, i-1]中所有元素小于等于A[i],A[i+1,n]中所有元素大于等于A[i]。同样可以使用递归的方法实现。不理解的可以参考归并排序。
时间复杂度O(nlog(n))
若干排序算法的Python实现方法及原理的更多相关文章
- 八大排序算法的 Python 实现
转载: 八大排序算法的 Python 实现 本文用Python实现了插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 描述 插入排序的基本操作就是将一个 ...
- 常用排序算法的python实现和性能分析
常用排序算法的python实现和性能分析 一年一度的换工作高峰又到了,HR大概每天都塞几份简历过来,基本上一天安排两个面试的话,当天就只能加班干活了.趁着面试别人的机会,自己也把一些基础算法和一些面试 ...
- 十大经典排序算法总结 (Python)
作业部落:https://www.zybuluo.com/listenviolet/note/1399285 以上链接是自己在作业部落编辑的排序算法总结- Github: https://github ...
- 一些排序算法的Python实现
''' Created on 2016/12/16 Created by freeol.cn 一些排序算法的Python实现 @author: 拽拽绅士 ''' '''值交换''' def swap( ...
- 朴素贝叶斯算法的python实现方法
朴素贝叶斯算法的python实现方法 本文实例讲述了朴素贝叶斯算法的python实现方法.分享给大家供大家参考.具体实现方法如下: 朴素贝叶斯算法优缺点 优点:在数据较少的情况下依然有效,可以处理多类 ...
- 几种常用排序算法的python实现
1:快速排序 思想: 任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序. 一趟快速排序的算法是: 1)设置 ...
- 基本排序算法的Python实现
本篇主要实现九(八)大排序算法,分别是冒泡排序,插入排序,选择排序,希尔排序,归并排序,快速排序,堆排序,计数排序.希望大家回顾知识的时候也能从我的这篇文章得到帮助. 为了防止误导读者,本文所有概念性 ...
- 经典排序算法及python实现
今天我们来谈谈几种经典排序算法,然后用python来实现,最后通过数据来比较几个算法时间 选择排序 选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理是每一次从待排序的数据 ...
- python基础===八大排序算法的 Python 实现
本文用Python实现了插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 描述 插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一 ...
随机推荐
- Sending forms through JavaScript
https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript As in the ...
- pg_restore数据库恢复指令
pg_restore restores a PostgreSQL database from an archive created by pg_dump. Usage: pg_restore [OP ...
- C语言 > 字符串和字符串函数
输入 gets() 函数 : 1.gets() 从标准输入设备读取字符串,以回车结束读取,使用'\0'结尾,回车符'\n'被舍弃没有遗留在缓冲区. 2.可以用来输入带空格的字符串. 3.可以无限读取, ...
- js算法初窥01(排序算法01-冒泡、选择、插入)
排序,我想大家一定经历过或者正在经历着.或许你不懂算法,对排序算法一无所知,但是你一定用过一些第三方库的api来一键排序,那么,在你享受便捷的同时,你是否想过它的底层是如何实现的?这样的算法实现方式是 ...
- git进阶
一.刚提交的代码,发现需要微调一下 刚刚最新提交了一段代码,然后跟前端说,接口好了.过了2分钟,前端跟你说,哎,兄弟,那个金额能不能返回整数,不要小数点. 这个时候一般我们通常会修改一下之后,再提交一 ...
- mysql数据库死锁的产生原因及解决办法
这篇文章主要介绍了mysql数据库锁的产生原因及解决办法,需要的朋友可以参考下 数据库和操作系统一样,是一个多用户使用的共享资源.当多个用户并发地存取数据 时,在数据库中就会产生多个事务同时存取同 ...
- 网络模型 - 每天5分钟玩转 Docker 容器技术(169)
本节我们讨论 Kubernetes 网络这个重要主题. Kubernetes 作为编排引擎管理着分布在不同节点上的容器和 Pod.Pod.Service.外部组件之间需要一种可靠的方式找到彼此并进行通 ...
- Python Web(Django)与SQL SERVER的连接处理
(开开心心每一天~ ---虫瘾师) Python Web(Django) 与SQL SERVRE的连接----Come QQ群:607021567(里面有很多开源代码和资料,并且python的游戏也有 ...
- 一个bug分析 ----------换个角度,有另外一个天地
有个接口是按修改时间(updated_time)排序的 优化后,有人反馈接口的返回值有问题 查了一下,反馈的数据是推荐过的(推荐操作是会更新updated_time的). 然后就认为是有人进行了推荐操 ...
- tkinter中frame布局控件(九)
frame控件 frame控件是将窗口分成好几个小模块,然后每个小模块中添加控件. 也就是将窗口合理的布局 由于和其他控件的操作基本一致,就不做注释了 import tkinter wuya = tk ...