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

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

之前总是觉得,不就是排序算法吗?有什么大不了的?网上、书上一查一大堆。但是换个角度想: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. Redis模块化基本介绍

    概要 Redis Modules System基本概念 基本应用 参考资料 1. Redis Modules System基本概念 Redis Modules System是4.0出现一大改动点,使得 ...

  2. java线程之线程通信控制

    在上篇我们看到,A线程往公共资源库(对象)提供了一条数据,然后B线程从库中提取了数据并打印出来. 实际项目中,我们不可能只往库中提供一条数据,而且库的大小也不会是无穷大的,那么我们就会有这样一 个需求 ...

  3. Search in rotated array two

    description: Follow up for "Search in Rotated Sorted Array":What if duplicates are allowed ...

  4. 界面渐变特效 -- CSS实现 -- 兼容IE8

    特别注意:里面的RGB颜色值必须要全写,不能使用缩写.左右:background: -webkit-gradient(linear, 0 0, 0 100%, from(#80c1e7), to(#2 ...

  5. php判断图片是否存在的几种方法

    在我们日常的开发中,经常需要用到判断图片是否存在,存在则显示,不存在则显示默认图片,那么我们用到的判断有哪些呢?今天我们就来看下几个常用的方法: 1.getimagesize()函数 getimage ...

  6. 用js来实现那些数据结构—目录

    首先,有一点要声明,下面所有文章的所有内容的代码,都不是我一个人独立完成的,它们来自于一本叫做<学习JavaScript数据结构和算法>(第二版),人民邮电出版社出版的这本书.github ...

  7. javascript 易漏点

    javascript 是一种解释型语言,不是java或c++那样的编译语言.javascript指令以普通文本形式传递给浏览器,然后依次解释执行.它们不必首先“编译”成只有计算机处理器能理解的机器码. ...

  8. Flask入门之Bootstrap介绍使用和Flask-Nav快速导航栏

    一.Bootstrap Bootstrap,来自 Twitter,是目前最受欢迎的前端框架. Python中,同样可以使用Bootstrap. 1. 导入Bootstrap库 from flask_b ...

  9. Java面向对象(一、封装)

    Java 封装 封装的概念 在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部份包装.隐藏起来的方法. 封装可以被认为是一个保护屏障,防止该类的代码 ...

  10. vue项目中解决type=”file“ change事件只执行一次的问题

    问题描述 在最近的项目开发中遇到了这样的一个问题,当我上传了一个文件时,我将获取到的文件名清空后,却无法再次上传相同的文件 <template> <div class="h ...