今天突然想到了一个问题:让你立即把堆排、快排等等排序算法写出来会不会,并且不能犯逻辑错误?

我说:不会,至少需要思考一下,并且可能还需要时间调试。

之前总是觉得,不就是排序算法吗?有什么大不了的?网上、书上一查一大堆。但是换个角度想: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实现方法及原理的更多相关文章

  1. 八大排序算法的 Python 实现

    转载: 八大排序算法的 Python 实现 本文用Python实现了插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 描述 插入排序的基本操作就是将一个 ...

  2. 常用排序算法的python实现和性能分析

    常用排序算法的python实现和性能分析 一年一度的换工作高峰又到了,HR大概每天都塞几份简历过来,基本上一天安排两个面试的话,当天就只能加班干活了.趁着面试别人的机会,自己也把一些基础算法和一些面试 ...

  3. 十大经典排序算法总结 (Python)

    作业部落:https://www.zybuluo.com/listenviolet/note/1399285 以上链接是自己在作业部落编辑的排序算法总结- Github: https://github ...

  4. 一些排序算法的Python实现

    ''' Created on 2016/12/16 Created by freeol.cn 一些排序算法的Python实现 @author: 拽拽绅士 ''' '''值交换''' def swap( ...

  5. 朴素贝叶斯算法的python实现方法

    朴素贝叶斯算法的python实现方法 本文实例讲述了朴素贝叶斯算法的python实现方法.分享给大家供大家参考.具体实现方法如下: 朴素贝叶斯算法优缺点 优点:在数据较少的情况下依然有效,可以处理多类 ...

  6. 几种常用排序算法的python实现

    1:快速排序 思想: 任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序. 一趟快速排序的算法是: 1)设置 ...

  7. 基本排序算法的Python实现

    本篇主要实现九(八)大排序算法,分别是冒泡排序,插入排序,选择排序,希尔排序,归并排序,快速排序,堆排序,计数排序.希望大家回顾知识的时候也能从我的这篇文章得到帮助. 为了防止误导读者,本文所有概念性 ...

  8. 经典排序算法及python实现

    今天我们来谈谈几种经典排序算法,然后用python来实现,最后通过数据来比较几个算法时间 选择排序 选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理是每一次从待排序的数据 ...

  9. python基础===八大排序算法的 Python 实现

    本文用Python实现了插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 描述 插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一 ...

随机推荐

  1. postgresql to_char 问题

    select create_time from  xxx; select to_char(create_time,'yyyy-MM-dd HH24:mm:ss') as  create_time fr ...

  2. Windows下对拍

    What is 对拍 Tool: 你的程序 可以输出正解的暴力程序 数据生成器 输出对比器 RP 用来干什么? 用来造数据,检验你的程序的正确性,以方便修改和出现未考虑到的情况 如何工作? 数据生成器 ...

  3. 基于Python的数据分析(1):配置安装环境

    数据分析是一个历史久远的东西,但是直到近代微型计算机的普及,数据分析的价值才得到大家的重视.到了今天,数据分析已经成为企业生产运维的一个核心组成部分. 据我自己做数据分析的经验来看,目前数据分析按照使 ...

  4. 基于ThreadPoolExecutor,自定义线程池简单实现

    一.线程池作用 在上一篇随笔中有提到多线程具有同一时刻处理多个任务的特点,即并行工作,因此多线程的用途非常广泛,特别在性能优化上显得尤为重要.然而,多线程处理消耗的时间包括创建线程时间T1.工作时间T ...

  5. REBEL IDEA热部署插件使用

    启动 一.在IDEA 的Plugins中搜索Jrebel for intellij 插件 二.https://my.jrebel.com/account/how-to-activate 注册或者使用f ...

  6. Robot Framework之测试用例分层实战

    1.1  测试用例的第一层(交互层) 1. 创建项目资源(Resource). 操作步骤: 点”项目名称”->右键,选New Resource,在弹窗Name 输入框输入资源名称 mykeywo ...

  7. day12 EL 表达式和国际化开发

    day12 EL 表达式和国际化开发 1. EL(Expression Language) 表达式简介 1.1 执行运算 1.2 获取web开发常用对象(el 中定义了11个隐式对象) 1.3 使用 ...

  8. MyBatis系列目录--5. MyBatis一级缓存和二级缓存(redis实现)

    转载请注明出处哈:http://carlosfu.iteye.com/blog/2238662 0. 相关知识: 查询缓存:绝大数系统主要是读多写少. 缓存作用:减轻数据库压力,提供访问速度. 1. ...

  9. ZooKeeper的使用---Java程序

    一.导入库 以下库存放在目录lib中: audience-annotations-0.5.0.jar jline-0.9.94.jar log4j-1.2.17.jar netty-3.10.6.Fi ...

  10. 第四章——训练模型(Training Models)

    前几章在不知道原理的情况下,已经学会使用了多个机器学习模型机器算法.Scikit-Learn很方便,以至于隐藏了太多的实现细节. 知其然知其所以然是必要的,这有利于快速选择合适的模型.正确的训练算法. ...