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

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实现

时间: 2024-11-10 07:27:04

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

七种常用排序算法

七种常用排序算法 一.常见排序算法一览: 时间复杂度: 是一个函数,它定量描述了该算法的运行时间. 空间复杂度:一个算法在运行过程中临时占用存储空间大小的量度. 稳定性:保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同就稳定,反之不稳定. 视觉直观感受 7 种常用的排序算法 二.算法C#实现: 1. 直接插入排序: using System; using System.Collections.Generic; using System.Linq; using Sys

几种常用排序算法温习

几种常用排序算法温习 一. 简单排序方法 1.直接插入排序 基本思想:顺序地将待排序的记录按其关键码的大小插入到已排序的记录子序列的适当位置. 算法代码: //直接插入排序 public static void InsertSort(SeqList<int> seq) { if (seq.IsEmpty() || seq.GetLength() == 1) return; Console.Write("1.1 简单排序 排序前:"); seq.Display(); int

常用排序算法的python实现

排序算是编程最基本的算法问题之一了,熟练掌握排序算法也能加深自己对数据结构的理解,也能提高自己的编程能力,以下为个人参考许多大神博客后对常用排序算法的学习总结. 目录: 概述 冒泡排序 直接插入排序 简单选择排序 希尔排序 堆排序 归并排序 快速排序 算法的比较与测试 参考 1. 概述 所谓排序(sorting)就是整理数据的序列,使其按照特定顺序排列的操作.排序在现实生活中(如整理书籍,表格数据等),在计算领域中(如二分查找,图论的最小生成树的Kruskal算法)均有重要意义,所以一种高效的排

视觉直观感受7种常用排序算法

视觉直观感受若干常用排序算法 1 快速排序 介绍: 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来,且在大部分真实世界的数据,可以决定设计的选择,减少所需时间的二次方项之可能性. 步骤: 从数列中挑出一个元素,称为 "基准"(pivo

几种常用排序算法 (一)

八大常用排序算法详细分析 包括复杂度: 排序有可以分为以下几类: (1).交换排序:冒泡排序.快速排序 (2).选择排序:直接选择排序.堆排序 (3).插入排序:直接插入排序.希尔排序 (4).归并排序 (5).基数排序(桶排序) 1.冒泡排序 顾名思义,冒泡排序就是用气泡从下往上冒的原理,将气泡(较小或较大的数)依次往前移. 具体做法(升序):设总共有N个元素,则至少需要进行N-1次冒泡.一次排序排序中,若前一个元素大于后一个元素,则交换两个元素,然后在依次判  断后面两两相邻元素大小并进行交

数据结构——排序——8种常用排序算法稳定性分析

首先,排序算法的稳定性大家应该都知道,通俗地讲就是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同.在简单形式化一下,如果Ai = Aj, Ai原来在位置前,排序后Ai还是要在Aj位置前. 其次,说一下稳定性的好处.排序算法如果是稳定的,那么从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用.基数排序就是这样,先按低位排序,逐次按高位排序,低位相同的元素其顺序再高位也相同时是不会改变的.另外,如果排序算法稳定,对基于比较的排序算法而言

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

http://www.cnblogs.com/wiki-royzhang/p/3614694.html 一年一度的换工作高峰又到了,HR大概每天都塞几份简历过来,基本上一天安排两个面试的话,当天就只能加班干活了.趁着面试别人的机会,自己也把一些基础算法和一些面试题整了一下,可以阶段性的留下些脚印——没办法,平时太忙,基本上没有时间写博客.面试测试开发的话,这些也许能帮得上一些. 这篇是关于排序的,把常见的排序算法和面试中经常提到的一些问题整理了一下.这里面大概有3个需要提到的问题: 虽然专业是数

几种常用排序算法(bubble、select、insert、shell、未完待续)

接下来两天重新看看几种常用的排序算法. 1.冒泡排序法 每次从 i=0开始比较相邻的元素,若arr[i]>arr[i+1],则交换它们.直到把最大的元素推向最后.回到 i=0,直至完成. 1 import java.util.Scanner; 2 class bubble 3 { 4 public static void main(String[] args) 5 { 6 int n,temp; 7 int i,j; 8 int[] arr=new int[10000]; 9 Scanner s

【轻松学排序算法】眼睛直观感受几种常用排序算法(转)

1 快速排序 介绍: 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来,且在大部分真实世界的数据,可以决定设计的选择,减少所需时间的二次方项之可能性. 步骤: 从数列中挑出一个元素,称为 "基准"(pivot), 重新排序数列,所有元素