排序算法学习,python实现
原创博文,转载请注明出处
利用周六周末的时间把几种基本的排序方法用python实现了一下,废话少说,直接上代码。
本文不注重基础知识的讲解,只做大致的描述,大家如果不清楚概念,自行查找资料。
直接插入排序:
每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。
def insert(arr):
l = len(arr)
for i in range(1,l):
if arr[i]<arr[i-1]:
temp =arr[i]
j=i-1
arr[j+1]=arr[j]
j=j-1
while j>=0 and arr[j]>temp:
arr[j+1]=arr[j] #元素后移
j=j-1
arr[j+1]=temp
return arr
arra=[98,36,-9,0,47,23,1,8,10,7]
print insert(arra)
折半插入排序:
折半插入排序就是就是将上面直接插入排序中查找有序子表的工作使用折半查找来实现,在确定出待插入位置后,就可以统一的向后移动元素。
# -*- coding: cp936 -*-
def find_ff(arr,x):#折半查找
size =len(arr)
low = 0
high = size-1
while low<=high:
mid =(low+high)/2
if arr[low]==x:
return low
elif arr[high]==x:
return high
elif arr[mid]==x:
return mid
elif arr[mid] > x:
high = mid-1
else:
low = mid+1 def insert_ff(arr):#升序
l = len(arr)
for i in range(1,l):
if arr[i]<arr[i-1]:
temp =arr[i]
j=i-1
low = 0
high = j
while low<=high:
mid = (low+high)/2
print 'mid',mid
if arr[mid] > temp:
high = mid-1
else:
low = mid+1
print 'high+1',high+1
print 'j',j
if j==0:
arr[j+1],arr[j]=arr[j],arr[j+1]
else:
print 'action 2 '
for x in range(j,high,-1):#移动元素
print 'x',x
arr[x+1]=arr[x]
arr[high+1]=temp
print arr
return arr arra=[98,36,-9,0,47,23,1,8,10,7]
print insert_ff(arra)
在分析折半插入排序时 一定要搞清楚元素的索引值。所以我在里面加入了print语句是为了测试而加入的 ,可以忽略。
希尔排序
def shell(arr):
l = len(arr)
h = l/2
while h>=1:
for i in range(l):
j = i
while j>=h and arr[j]<arr[j-h]:
arr[j],arr[j-h]=arr[j-h],arr[j]
h=h/2
return arr
arra=[98,36,-9,0,47,23,1,8,10,7]
print shell(arra)
交换排序 : 冒泡排序和快速排序
冒泡排序比较简单
# -*- coding: cp936 -*-
def bubble(arr):#降序
size = len(arr)
for i in range(size-1):
for j in range(i,size-1):
if arr[j+1]>arr[j]:
arr[j+1],arr[j]=arr[j],arr[j+1] return arr arra=[98,36,-9,0,47,23,1,8,10,7]
print bubble(arra)
快速排序 :对冒泡排序的一种改进,基本思想是基于分治的
# -*- coding: cp936 -*-
def partition(data,low,high):
if low<high:
x = data[low]#以第一个元素作为枢轴值
while low<high: #循环跳出条件
while low<high and data[high]>=x:
high -= 1
data[low]=data[high]#将小于枢轴值得元素移到左端
while low<high and data[low]<=x:
low += 1
print low
data[high]=data[low]#将大于枢轴值的元素移到右端
data[low]=x
return low
def quick(arr,low,high):
if low < high:
pivotop = partition(arr,low,high)
quick(arr,low,pivotop-1)
quick(arr,pivotop+1,high)
return arr arra=[98,36,-9,0,47,23,1,8,10,7]
print quick(arra,0,len(arra)-1)
在这儿我们举了一个特例,就是第一个元素大于后面的所有元素,在测试过程中发现了好多问题,比如第六行和第九行再次加入了low<high的判断条件是为了避免边界条件问题,边界条件作为测试过程的重要环节,由于逻辑性较强,所以比较困难调试。
选择排序 :简单排序和堆排序
简单排序比较简单实现如下
def simple(arr):
size = len(arr)
for i in range(size):
mini = arr[i]
for j in range(i,size):
if arr[j] < mini:
mini = arr[j]
arr[i],arr[j]=arr[j],arr[i]
return arr
arra=[98,36,-9,0,47,23,1,8,10,7]
print simple(arra)
堆排序:与简单排序不同,在排序过程中,将L[1...n]看成是一棵完全二叉树的顺序存储结构,利用二叉树中双亲节点和孩子结点的内在关系(搞清楚各种二叉树的区别),在当前无序区选择关键字最大或最小的元素。
堆的定义:n个关键字序列L[1...n]成为堆,当且仅当满足下列条件之一:
1. L(i)<=L(2i),且L(i)<=L(2i+1) 称为小根堆,也就是满足双亲节点小于孩子节点
2. L(i)>=L(2i),且L(i)>=L(2i+1) 称为大根堆,也就是满足双亲节点大于孩子节点
堆排序的关键是构建初始栈,n个结点的完全二叉树,最后一个结点是第n/2个结点的孩子。对第n/2个结点为根的子树筛选,使该子树成为堆。之后向前依次对各结点为根的子树进行筛选(对于大根堆:若根结点的关键值小于孩子结点中关键值较大者,则交换)。
堆排序这儿还是遇到了不少麻烦,一定要理清脉络。有一点需要注意,一定要考虑到只有左孩子没有右孩子的情况,网上好多版本都没有考虑到这一特殊情况,因为加入没有右孩子结点你再载入值得话就会触发异常IndexError: list index out of range。
# -*- coding: cp936 -*-
def buildHeap(arr):
size = len(arr)
for i in range(getParent(size-1),-1,-1):
adjustDown(arr,size-1,i) #注意 size-1不是size def getParent(k):
if k%2==1:
return int(k/2)
else:
return k/2-1 def adjustDown(arr,size,k):#一定要注意size的值
print 'k',k
left = 2*k+1
right = left+1
maxp = k
if left<size and arr[k]<arr[left]:#先判断左孩子
maxp = left
if left<size and right<size:#假如有右孩子,取两个孩子结点的最大值
maxlr = left if arr[left]>arr[right] else right
if left<size and right<size and arr[k]<arr[maxlr]:
maxp = maxlr
if maxp!=k:
arr[maxp],arr[k]=arr[k],arr[maxp]
print arr
adjustDown(arr,size,maxp) def heap(arr):
size = len(arr)
buildHeap(arr)
print 'build',arr
for i in range(size-1,-1,-1):#size-1
arr[i],arr[0]=arr[0],arr[i]
print arr[i],arr[0]
adjustDown(arr,i,0)
return arr arra=[98,36,-9,47,23,1,8]
print heap(arra)
归并排序:
归并的含义是将两个或两个以上的有序表组合成一个新的有序表。最常见的是2-路归并排序。在程序设计中merge()是把两个有序表合并的操作。递归形式的2-路归并排序算法是基于分治的,其过程如下:
分解:将含有n个元素的待排序表分成各含n/2个元素的子表,采用 2-路归并排序算法对两个子表递归的进行排序
合并:合并两个已排序的子表得到排序结果。
性能分析: 空间复杂度为 O(n),每一趟归并的时间的复杂度为O(n),共需要进行log2n趟归并,所以算法的时间复杂度为 O(nlog2n)。 merge()操作并不会改变相同关键字记录的相对次序,故算法稳定。
def mergeSort(arr):
if len(arr)<=1:
return arr
mid = len(arr)/2
left=mergeSort(arr[:mid])
right=mergeSort(arr[mid:])
return merge(left,right) def merge(left,right):
result=[]
i,j=0,0
while len(left)>i and len(right)>j:
if left[i]<=right[j]:
result.append(left[i])
i+=1
else:
result.append(right[j])
j+=1
result +=left[i:]
result +=right[j:]
return result arra=[98,36,-9,0,47,23,1,8,10,7]
print mergeSort(arra)
基数排序:
园内 有一篇讲解基数排序的,http://www.cnblogs.com/Braveliu/archive/2013/01/21/2870201.html,图文并茂,很不错,具体概念就不讲解了。这儿我就用python实现一下吧。
# -*- coding: cp936 -*-
def radixSort_LSD(arr,d):
for i in xrange(d):
S = [[] for j in xrange(10)]
for x in arr:
S[x/(10**i)%10].append(x)
arr = [x for y in S for x in y]
return arr def radixSort_MSD(arr,d):
r = int(d-1)
if r>=0:
S = [[] for j in xrange(10)]
L =[]
for x in arr:
S[x/(10**r)%10].append(x)
for y in S:
M=radixSort_MSD(y,r)
L.append(M)
arr = [x for y in L for x in y]
return arr arra=[98,36,9,0,47,23,1,8,10,7]
print radixSort_MSD(arra,2)
print radixSort_LSD(arra,2)
注意MSD和LSD的区别,
LSD的排序方式由数值的最右边(低位)开始,而MSD则相反,由数值的最左边(高位)开始。
注意一点:LSD的基数排序适用于位数少的数列,如果位数多的话,使用MSD的效率会比较好。
MSD的方式与LSD相反,是由高位数为基底开始进行分配,但在分配之后并不马上合并回一个数组中,而是在每个“桶子”中建立“子桶”,将每个桶子中的数值按照下一数位的值分配到“子桶”中。所以在MSD中我构建了一个L作为子桶。 有没有感觉python非常优雅,简简单单的几句代码就解决了问题。
计数排序:
计数排序一般应用于序列元素是正整数的时候,计数排序不是比较排序,排序的速度快于任何比较排序算法。在学习计数排序的时候还是费了很大功夫,一直搞不懂其中的道理。
# -*- coding: cp936 -*-
def countSort(arr):
size = len(arr)
mini = maxp = arr[0]
for i in arr:#找出最大最小值
if i<mini:
mini = i
if i>maxp:
maxp = i
bound = maxp - mini +1
count = [0 for i in range(bound)]
sorted_arr = [0 for i in range(size)]
for i in range(size):
count[arr[i]-mini]+=1#arr的元素值个数对应count的元素值,
x=0
for i in range(mini,maxp+1):
for j in range(0,count[i-mini]):
sorted_arr[x]=i
x+=1 return sorted_arr
arra=[98,36,5,47,23,1,8]
print countSort(arra)
计数排序的时间复杂度为O(n),这是其他排序方法难以达到的(其他算法的时间复杂度要么为O(n2),要么为O(nlogn))。
排序算法学习,python实现的更多相关文章
- 第四百一十五节,python常用排序算法学习
第四百一十五节,python常用排序算法学习 常用排序 名称 复杂度 说明 备注 冒泡排序Bubble Sort O(N*N) 将待排序的元素看作是竖着排列的“气泡”,较小的元素比较轻,从而要往上浮 ...
- 八大排序算法的 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实现(三)冒泡排序
代码: #coding:utf-8 #author:徐卜灵 #交换排序.冒泡排序 L = [1, 3, 2, 32, 5, 4] def Bubble_sort(L): for i in range( ...
- 基本排序算法的Python实现
本篇主要实现九(八)大排序算法,分别是冒泡排序,插入排序,选择排序,希尔排序,归并排序,快速排序,堆排序,计数排序.希望大家回顾知识的时候也能从我的这篇文章得到帮助. 为了防止误导读者,本文所有概念性 ...
- 经典排序算法及python实现
今天我们来谈谈几种经典排序算法,然后用python来实现,最后通过数据来比较几个算法时间 选择排序 选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理是每一次从待排序的数据 ...
- python基础===八大排序算法的 Python 实现
本文用Python实现了插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 描述 插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一 ...
随机推荐
- typeof + instanceof+toString+constructor什么推理javascript数据类型
一个.typeof JS这些变量是弱类型(这是弱类型)的,它可以不管用来存储数据的类型的. typeof 数据类型可用于检测给定的变量.可能的返回值: 1. 'undefined' --- 这个值没有 ...
- PHP课程十大 PHP图像处理功能和实现的验证码
假如你喜欢这个博客,访问这个博客地址:http://blog.csdn.net/junzaivip 总结: gd绘图库: 数学函数 PHP图片处理函数 图片处理函数使用场景 1.验证码 2.缩放 3. ...
- 求和问题(DFS)
输入: n=4 a={1,2,4,7} k=13 输出: YES 输入: n=4 a={1,2,4,7} k=13 输出: NO 选出若干数,使它们的和恰好为k #include <stdio. ...
- C# Windows服务的创建、安装、调试
一.查看已有的Windows服务 选择菜单"开始"-〉"控制面板"-〉"管理工具"-〉"服务"来查看现有系统中的服务 二 ...
- 浅谈JavaScript中的柯里化函数
首先,不可避免的要引经据典啦,什么是柯里化函数呢(from baidu): 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返 ...
- 关于启动调试时,总是启动多个web端口的问题
在一个解决方案中,经常包含多个web项目,当设置某一个web项目为起始项目后,启动调试,会发现其他的web项目的端口也会一起打开,显示在电脑的右下方,其实开启其他端口有时是没必要的,只是多占用了系统内 ...
- 你知道OneNote的OCR功能吗?office lens为其增大威力,中文也识别
原文:[原创]你知道OneNote的OCR功能吗?office lens为其增大威力,中文也识别 OneNote提供了强大的从图片中取出文字的功能,大家只要装上了桌面版OneNote(本人用的2013 ...
- 6、Cocos2dx 3.0游戏开发的基本概念找个小三场比赛
重开发人员的劳动成果,转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/27689713 郝萌主友情提示: 人是习惯的产物,当你 ...
- 基于 自己定义注解 和 aop 实现使用memcache 对数据库的缓存 演示样例
好久没更新blog了,在新公司打拼了两个月,每天都从早忙到晚,学到了非常多东西,可是没有时间来更新blog了.... 以下開始解说这次的主题 公司老大让我研究 ocs 就是阿里云的 开放缓存服务 点击 ...
- android学习8(ListView高级使用)
ListView在android更开放的,于是继续ListView说明使用. 首先创建一个android项目,项目名为ListViewTest. ListView的简单使用 改动布局文件,改动后代码例 ...