1:快速排序

思想:

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

一趟快速排序的算法是:
1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]赋给A[i];
4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]赋给A[j];
5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。
 
注意:快速排序不会直接得到最终结果,只会把比k大和比k小的数分到k的两边。(你可以想象一下i和j是两个机器人,数据就是大小不一的石头,先取走i前面的石头留出回旋的空间,然后他们轮流分别挑选比k大和比k小的石头扔给对面,最后在他们中间把取走的那块石头放回去,于是比这块石头大的全扔给了j那一边,小的全扔给了i那一边。只是这次运气好,扔完一次刚好排整齐。)为了得到最后结果,需要再次对下标2两边的数组分别执行此步骤,然后再分解数组,直到数组不能再分解为止(只有一个数据),才能得到正确结果。
 
python实现代码:
#*-* coding: utf-8 *-*
import random
# produce random numbers to be sorted
s = []
for i in range(0,100):
s.append(random.randint(1,100))
print(s[i]),
#
print("\nbegin")
def partition(inlist,start,end):
i = start
j = end
k = inlist[i]
while i<j:
while i<j and inlist[j]>=k:
j = j-1
inlist[i]=inlist[j]
while i<j and inlist[i]<=k:
i = i+1
inlist[j]=inlist[i]
inlist[i]=k
return i def quickSort(inlist,start,end):
if start>=end:
return
middle = partition(inlist,start,end)
quickSort(inlist,start,middle-1)
quickSort(inlist,middle+1,end) quickSort(s,0,len(s)-1)
for i in s:
print "%d " %i,
print("done")

2:直接插入排序

思想:

每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。
第一趟比较前两个数,然后把第二个数按大小插入到有序表中; 第二趟把第三个数据与前两个数从前向后扫描,把第三个数按大小插入到有序表中;依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程。
python 代码:
#*-* coding: utf-8 *-*
import random
# produce random numbers to be sorted
s = []
for i in range(0,100):
s.append(random.randint(1,100))
print(s[i]),
#
print("\nbegin") j=0
for i in range(1,len(s)):
if s[i]<s[i-1]:
temp = s[i]
j=i-1
while j>=0 and s[j]>temp:
s[j+1]=s[j]
s[j]=temp
j=j-1
for i in s:
print "%d " %i,
print("\ndone")

3:冒泡排序

思想:

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

python 代码:

#*-* coding: utf-8 *-*
import random
# produce random numbers to be sorted
s = []
for i in range(0,100):
s.append(random.randint(1,100))
print(s[i]),
#
print("\nbegin") i = len(s)-1
while i>0:
j=0
for j in range(0,i):
if s[j+1]<s[j]:
temp = s[j]
s[j]=s[j+1]
s[j+1]=temp
j = j+1
i = i-1
for i in s:
print "%d " %i,
print("\ndone")

4:桶排序

思想:

假定:输入是由一个随机过程产生的[0, 1)区间上均匀分布的实数。将区间[0, 1)划分为n个大小相等的子区间(桶),每桶大小1/n:[0, 1/n), [1/n, 2/n), [2/n, 3/n),…,[k/n, (k+1)/n ),…将n个输入元素分配到这些桶中,对桶中元素进行排序,然后依次连接桶输入0 ≤A[1..n] <1辅助数组B[0..n-1]是一指针数组,指向桶(链表)。

太难懂了,举个简单的例子:

一年的全国高考考生人数为500 万,分数使用标准分,最低100 ,最高900 ,没有小数,你把这500 万元素的数组排个序。
我们发现,这些数据都有特殊的条件: 100=<score<=900。那么我们就可以考虑桶排序这样一个“投机取巧”的办法、让其在毫秒级别就完成500万排序。
方法:创建801(900-100)个桶。将每个考生的分数丢进f(score)=score-100的桶中。这个过程从头到尾遍历一遍数据只需要500W次。然后根据桶号大小依次将桶中数值输出,即可以得到一个有序的序列。而且可以很容易的得到100分有***人,501分有***人。
python代码:
#*-* coding: utf-8 *-*
import random
# produce random numbers to be sorted
#10000 numbers,range in (0,100)
s = []
for i in range(0,10000):
s.append(random.randint(0,100))
#print(s[i]),
#
print("\nbegin")
r = {}
for i in range(0,101):
r[i]=[]
for i in s:
r[i].append(i)
f = file("r.txt","w")
for i in range(0,101):
for j in r[i]:
f.write(str(j)+',')
print("\ndone")

5:归并排序

思想:

归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个有序的子序列,再把有序的子序列合并为整体有序序列。

python代码:

#*-* coding: utf-8 *-*
import random
# produce random numbers to be sorted
s = []
for i in range(0,100):
s.append(random.randint(1,100))
print(s[i]),print("\nbegin") def spli(inlist):
if len(inlist)<=1:
return inlist
num = len(inlist)/2
left = spli(inlist[0:num])
right = spli(inlist[num:])
return sor(left,right)
def sor(left,right):
#print(left)
#print(right)
l = 0
r = 0
result =[]
while l<len(left) and r <len(right):
if left[l]<right[r]:
result.append(left[l])
l =l+1
else:
result.append(right[r])
r = r+1
result = result+right[r:]
result = result+left[l:]
return result
s=spli(s)
for i in s:
print "%d " %i,
print("\ndone")

6:堆排序

思想:

1.什么是堆?

堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:

Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]或者Key[i]>=Key[2i+1]&&key>=key[2i+2]

即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。

堆分为大顶堆和小顶堆,满足Key[i]>=Key[2i+1]&&key>=key[2i+2]称为大顶堆,满足 Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]称为小顶堆。由上述性质可知大顶堆的堆顶的关键字肯定是所有关键字中最大的,小顶堆的堆顶的关键字是所有关键字中最小的。

2.堆排序的思想

利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性,使得每次从无序中选择最大记录(最小记录)变得简单。

其基本思想为(大顶堆):

1)将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无序区;

2)将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n];

3)由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,......Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2....Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。

操作过程如下:

1)初始化堆:将R[1..n]构造为堆;

2)将当前无序区的堆顶元素R[1]同该区间的最后一个记录交换,然后将新的无序区调整为新的堆。

python 代码:

#*-* coding: utf-8 *-*
import random
# produce random numbers to be sorted
s = []
count=0
for i in range(0,100):
s.append(random.randint(1,100))
print(s[i]),
#
print("\nbegin")
def heap_sort(inlist):
for start in range((len(inlist)-2)/2,-1,-1):#1:初始化堆:从最底层开始建树,并且保证是堆
sift_down(inlist,start,len(inlist)-1)
for end in range(len(inlist)-1,0,-1):#2:将堆顶元素与最后一个元素交换,调整
inlist[0],inlist[end]=inlist[end],inlist[0]
sift_down(inlist,0,end-1)
return inlist def sift_down(inlist,start,end):
"""调整算法:从父节点、左孩子节点、右孩子节点三者中选择最大者跟父节点进行交换
(交换之后可能造成被交换的孩子节点不满足堆的性质,
因此每次交换之后要重新对被交换的孩子节点进行调整)"""
root = start
while True:
global count
count=count+1
child = 2*root +1#左节点
if child>end:
break
if child+1<=end and inlist[child]<inlist[child+1]:#左节点比右节点小
child = child+1#保证child对应的是左右节点中最大的
if inlist[root]<inlist[child]:#如果root不是最大,交换
inlist[root],inlist[child]=inlist[child],inlist[root]
root=child
else:
break
heap_sort(s)
for i in s:
print (i),
print("\ndone")
print(count)

6种算法比较次数的比较

随机生成10000的数据

  快速排序  直接插入排序 冒泡排序 桶排序 归并排序 堆排序
比较次数  512689  24795124  24934964  10000  120275  128265
效率  NlogN  N*N  N*N  N  NlogN  NlogN  

很容易可以看出:

1:桶排序是最快的,但使用范围有限,排序的标准和数据的属性是一致的

2:快速排序、归并排序和堆排序都是NlogN的,但具体还是差别的,随机数据来看,比较次数:归并《堆《快速

有序序列的影响:

快速排序:有序》》》》(远大于)无序

直接插入:有序《无序

冒泡:有序《无序

桶排序:无差别

归并:有序《无序

堆排序:有序》无序

几种常用排序算法的python实现的更多相关文章

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

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

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

    作者:waterxi 原文链接 背景 一年一度的换工作高峰又到了,HR大概每天都塞几份简历过来,基本上一天安排两个面试的话,当天就只能加班干活了.趁着面试别人的机会,自己也把一些基础算法和一些面试题整 ...

  3. 面试中常用排序算法的python实现和性能分析

    这篇是关于排序的,把常见的排序算法和面试中经常提到的一些问题整理了一下.这里面大概有3个需要提到的问题: 虽然专业是数学,但是自己还是比较讨厌繁琐的公式,所以基本上文章所有的逻辑,我都尽可能的用大白话 ...

  4. 用 Java 实现的八种常用排序算法

    八种排序算法可以按照如图分类 交换排序 所谓交换,就是序列中任意两个元素进行比较,根据比较结果来交换各自在序列中的位置,以此达到排序的目的. 1. 冒泡排序 冒泡排序是一种简单的交换排序算法,以升序排 ...

  5. 常用排序算法的Python实现

    冒泡排序 算法思想: 对于一组需要排序的数据,对于相邻的两个数进行比较,使较大(或者较小)的数一直向后推,经过多层排序之后,使整个序列是有序的. 算法实现: def bubble_sort(L): l ...

  6. Java种八种常用排序算法

    1 直接插入排序 经常碰到这样一类排序问题:把新的数据插入到已经排好的数据列中. 将第一个数和第二个数排序,然后构成一个有序序列 将第三个数插入进去,构成一个新的有序序列. 对第四个数.第五个数……直 ...

  7. 几种常用排序算法代码实现和基本优化(持续更新ing..)

    插入排序(InsertSort): 插入排序的基本思想:元素逐个遍历,在每次遍历的循环中,都要跟之前的元素做比较并“交换”元素,直到放在“合适的位置上”. 插入排序的特点:时间复杂度是随着待排数组的有 ...

  8. 面试中常用排序算法实现(Java)

    当我们进行数据处理的时候,往往需要对数据进行查找操作,一个有序的数据集往往能够在高效的查找算法下快速得到结果.所以排序的效率就会显的十分重要,本篇我们将着重的介绍几个常见的排序算法,涉及如下内容: 排 ...

  9. Python实现常用排序算法

    Python实现常用排序算法 冒泡排序 思路: 它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完 ...

随机推荐

  1. Java 访问权限控制 小结

    总所周知,Java提供了访问权限修饰词,以供类库开发人员向客户端程序员指明哪些是可用的,哪些是不可用的. 访问权限控制的等级,从最大权限到最小权限依次为:public.protected.包访问权限( ...

  2. Reactor模式是什么(转载)

    一.Reactor模式是什么反应器设计模式(Reactor pattern)是一种为处理并发服务请求,并将请求提交到一个或者多个服务处理程序的事件设计模式.当客户端请求抵达后,服务处理程序使用多路分配 ...

  3. PAT 1030 完美数列

    https://pintia.cn/problem-sets/994805260223102976/problems/994805291311284224 给定一个正整数数列,和正整数 p,设这个数列 ...

  4. 正则awk和查看文件行数

    [root@WebServer aa]# cat oldboy.txt I am oldboy myqq is 49000448[root@WebServer aa]# cat oldboy.txt ...

  5. [洛谷P1640][SCOI2010]连续攻击游戏

    题目大意:有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.每种装备最多只能使用一次,且只能使用其中一种属性.装备所使用的属性值必须从1开始连续.问最多能攻击多少次? ...

  6. Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) B

    B. Problems for Round time limit per test 2 seconds memory limit per test 256 megabytes input standa ...

  7. Spring随笔 —— IOC配置的三种不同方式简介

    在spring framework中,IOC的配置是最基础的部分,常见的配置方式有基于xml文件和基于注解的配置方式.除了这两种配置方式之外,今天这里再介绍另一种配置方式,先用小demo重温下我们熟悉 ...

  8. MFC 对话框透明效果

    网上找的资料自己改了改,在这里记录和分享一下,主要是TransparentWnd函数. 在子类的OnShowWindow函数中调用 ShowWindowAlpha() #pragma once tem ...

  9. CI框架浅析

    CI框架浅析(全篇)     业余花了点时间看看CodeIgniter框架(简称CI),CI目前的稳定版本是 3.X,4.0版本已经出来了,但还在测试中,所以我分析的还是 3.x 版本. CI是一个很 ...

  10. [CVPR2018]Learning to Adapt Structured Output Space for Semantic Segmentation

    学习适应结构化输出空间进行语义分割 在语义分割场景中,虽然物体在外表上不同,但是他们的输出是结构化且共享很多例如空间分布, 局部内容等信息.所以作者提出了multi-level的输出空间adaptat ...