python实现常见排序算法

1 篇文章 0 订阅
1 篇文章 0 订阅

一、冒泡排序

冒泡排序可以说是我们学习排序算法时最先学习的一种算法,冒泡排序的算法核心思想就是依次遍历需要排序的列表,比较相邻两元素的大小,将较大的元素放到后一位,较小的元素放到前一位,这样通过一次遍历,集合中最大的元素就位于列表的最后位置,一个包含n个元素的列表通过遍历n-1次,就可以获得排序后的列表,例如:
一个列表中包含的元素为: 4 5 3 1 2
1,首先遍历列表,用index表示遍历的元素下标,初始为index=0,比较与后一元素的大小,明显[index]<[index+1],元素顺序不变
2,将index+1,此时index=1,与后一个元素比较大小,此时有[index]>[index+1],这时候交换前后元素的位置,交换后的列表为:4 3 5 1 2
3,继续将index+1,有[index]>[index+1],交换元素位置,交换后大小列表为:4 3 1 5 2
4,继续将index+1,有[index]>[index+1],交换元素位置,交换后大小列表为:4 3 1 2 5,此时已经遍历到列表最后一位,我们发现元素的最大值已经位于列表的最后位置
5,重复上面的方法,最后得到最终结果

代码演示:

#冒泡排序 
import random
def bubblrSort(sequence):
    length=len(sequence)
    for i in range(length-1):
        for j in range(length-i-1):
            if(sequence[j] > sequence[j+1]):
                sequence[j],sequence[j+1]=sequence[j+1],sequence[j]
#测试   
a_list=list(range(20))
random.shuffle(a_list)
print("排序前:",a_list)
bubblrSort(a_list)
print("排序后:",a_list)

排序前: [8, 7, 17, 2, 9, 3, 11, 6, 14, 4, 13, 15, 5, 18, 10, 1, 12, 19, 0, 16]
排序后: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

二、选择排序

通过观察冒泡排序我们发现,冒泡排序时,为了将最大数交换到最后,我们在一次排序时,往往会进行多次交换,使得最大数冒泡到最后,这是非常消耗资源的,我们思考,有没有改进的措施?
如何,在一次排序过程中,我们交换的不是相邻元素,而是在一次排序时记录下最小或者最大元素的位置,在一次排序完毕后,再把最小元素放置在第一位或者把最大元素放置在最后,这样,每次排序需要进行一次交换,减小了交换次数,同时减小了资源消耗。这就是选择排序,选择排序的核心就是定义一个基准,后面的元素与这个基准进行比较,若是元素小于基准,则将此元素定位基准,依次往下遍历比较,最后的基准就是列表中元素的最小值,其具体的过程如下:
一个列表中包含的元素为: 4 5 3 1 2,我们先定义最小值下标minIndex=0,正在遍历的元素下标为index,初始值为minIndex+1
1,遍历列表,我们发现[minIndex]<[index],则minIndex不变,index+1
2,再次遍历,此时index=2,我们发现[minIndex]>[index],则将index的值赋值给minIndex
3,依次往下遍历,我们发现,依次遍历结束后,minIndex的值为3,就是最小值的下标,将这个元素与第一个元素进行交换,列表变为:1 5 3 4 2,一次遍历时只要一次交换即可将一个最大或最小值元素放置在正确位置
4,将minIndex=1,重复上面的过程,即可得到正确的结果

代码演示:

#选择排序
import random
def selectionSort(sequence):
    length=len(sequence)
    for i in range(length):  
        minIndex=i
        for j in range(i+1,length):
            if(sequence[minIndex]>sequence[j]):
                minIndex=j
        if minIndex != i:
            sequence[i],sequence[minIndex]=sequence[minIndex],sequence[i]
#测试
a_list=list(range(20))
random.shuffle(a_list)
print("排序前:",a_list)
selectionSort(a_list)
print("排序后:",a_list)   

排序前: [10, 9, 4, 13, 6, 12, 2, 1, 0, 11, 3, 15, 17, 18, 14, 5, 8, 7, 16, 19]
排序后: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

三、插入排序

插入排序的过程应该是最容易理解的一种,他的核心思想就是将一个元素元素插入到一个已经排好序的列表中,我们只要找到元素只要找到元素应该插入的位置,直接插入元素即可,如列表中包含元素1 2 3 5 ,我们需要插入元素4,我们只要找到比4小的元素,在后面插入即可
在实际的过程中,我们会将一个列表中第一个元素第一位哨兵元素,及默认第一个元素就是一个排序好的元素,后面的是需要插入的元素,如列表4 5 3 1 2
我们默认第一个元素4是哨兵元素,首先我们插入5,得到的有序列表为4 5,然后在4 5中插入3 得到3 4 5依次插入,得到最后的有序列表

代码演示:

#插入排序
import random
def insertSort(sequence):
    length=len(sequence)
    for i in range(1,length):
        for j in range(i):
            if(sequence[i] < sequence[j]):
                sequence.insert(j,sequence[i])
                sequence.pop(i+1)
#测试
a_list=list(range(20))
random.shuffle(a_list)
print("排序前:",a_list)
sort(a_list)
print("排序后:",a_list)     

排序前: [6, 14, 2, 18, 15, 9, 8, 13, 3, 1, 12, 4, 19, 17, 11, 16, 7, 0, 10, 5]
排序后: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

四、希尔排序

在观察插入排序的过程中,我们发现,如果是给定一个有序的序列,然后在对其插入元素,那么这是一个很快速的过程,但是在实际的过程中,我们给定的序列往往都是无序的,那么我们就会思考,如果我们可以将一个序列变为有序,或者相对有序的话,那么再对其进行插入排序之后就会使得算法性能提高,希尔排序的核心思想就是如此,希尔排序分为两部分,首先是将一个无序的列表变为一个相对有序的列表,然后再对其进行插入排序,所以,如何使得一个列表变为相对有序,是这个算法的重要一部分。
给定一组数据 5 2 1 4 7 8 3 0 9 6
我们发现如果将5定位哨兵元素,对其后面的元素依次进行插入排序,可获得一个有序的序列
但是,如果我们不是按照依次抽取,而是每隔5个抽取成一个新的序列,在进行插入的话,序列的无序性会降低,如,每隔五个进行抽取,即5–8,2–3,1–0,4–9,7–6,对其分别进行插入排序,结果为:5 2 0 4 6 3 1 9 7,则相对与原来序列,元素的无序性将降低,如果每隔两个进行抽取,则抽取的元素为5 1 7 3 9 与 2 4 8 0 6分别进行插入排序,得到的序列为1 0 3 2 5 4 7 6 9 8元素无序性大大降低,当抽取的间隔变为1时,就是一个正常的插入排序,此时,核心的算法思想已经阐述完毕。

代码演示

#修改后的插入排序
def insertSort( sequence,gap=1):#gap表示步长,即抽取元素的间隔
    length=len(sequence)
    i=gap
    while(i<length):
        nextItem=sequence[i]
        j=i
        while(j > gap-1 and nextItem < sequence[j-gap]):
            sequence[j]=sequence[j-gap]
            j-=gap
        sequence[j]=nextItem
        i+=1
 #希尔排序
import random
def shellSort(sequence):
    n = len(sequence)//2#n表示抽取步长
    while n >= 1:
        insertSort(sequence,n)
        #n值逐渐减小,知道等于一时,就是普通插入排序
        n=n//2
#测试
a_list=list(range(20))
random.shuffle(a_list)
print(a_list)
shellSort(a_list)
print(a_list)

排序前: [1, 3, 15, 18, 4, 19, 9, 12, 5, 10, 16, 2, 8, 0, 6, 14, 17, 13, 11, 7]
排序后: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

五、快速排序

快速排序也是一种较容易理解的排序算法,核心思想就是,在给定的一个序列中,拿出一个元素作为基准,遍历此序列,将比基准元素大的所有元素放在基准元素右边,小的所有元素放在基准元素左边,在对基准元素的左右两边进行快速排序,依次递归,最终得到一个有序的序列

代码实现

#快速排序
def quickSort(sequence):
    if len(sequence) < 2:
        return sequence
    baseValue=sequence[0]
    left=[item for item in sequence[1:] if item<baseValue]
    eqArray=[item for item in sequence[0:] if item==baseValue]
    right=[item for item in sequence[1:] if item>baseValue]
    return quickSort(left)+eqArray+quickSort(right)
#测试
a_list=list(range(20))
random.shuffle(a_list)
print("排序前:",a_list)
print("排序后:",quickSort(a_list))

排序前: [19, 11, 1, 0, 10, 2, 14, 7, 12, 13, 8, 17, 3, 9, 6, 15, 16, 18, 5, 4]
排序后: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

六、并归排序

并归排序也是一种较为常见的排序方式,所谓并归排序,就是对于两个有序序列l1与l2进行合并,使得合并后的序列依旧有序,如图所示
在这里插入图片描述
已知一个序列3 4 1 5 0 2
我们依次将这个序列划分为一个个子序列,最后得到只包含一个元素的子序列,然后将左边最下方的子序列有序合并得到序列3 4 再将3 4 与序列 1 有序合并 得到序列 1 3 4,右边同理可以得到0 2 5再将1 3 4与0 2 5有序合并即可得到最终有序序列
所以说,归并排序也可以分为两部分,第一部分,是将一个无序序列拆分为一个个子序列,然后再将一个个子序列合并为有序序列,其算法的难点时如何实现两个有序集合的合并。

#归并排序
#合并两个有序集合
import random
def mergeSortArrays(sequence1,sequence2):
    index_1=0
    index_2=0
    sequence1_length=len(sequence1)
    sequence2_length=len(sequence2)
    sequence=[]
    while index_1<sequence1_length and index_2<sequence2_length:
        if sequence1[index_1] < sequence2[index_2]:
            sequence.append(sequence1[index_1])
            index_1+=1
        else:
            sequence.append(sequence2[index_2])
            index_2+=1
    if index_1==sequence1_length:
        sequence += sequence2[index_2:sequence2_length]
    else:
        sequence += sequence1[index_1:sequence1_length]
    return sequence
#归并排序
def mergeSort(sequence):
    length=len(sequence)
    if length <= 1:
        return sequence
    else:
        index=length//2
        l1=sequence[0:index]
        l2=sequence[index:length]
        return mergeSortArrays(mergeSort(l1),mergeSort(l2))
a_list=list(range(20))
random.shuffle(a_list)
print("排序前:",a_list)
print("排序后:",mergeSort(a_list))

排序前: [16, 7, 19, 17, 0, 6, 9, 4, 15, 8, 2, 13, 5, 11, 14, 1, 10, 18, 3, 12]
排序后: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

七、基数排序

基数排序又称桶排序,顾名思义,就是有一个个的桶子,将每个数都依次放入自己应该在的那个桶子中
有下列几个数
81, 22, 73, 93, 143, 14, 55, 65, 28, 139
基数排序第一步为,将个位数相同的依次放入不同的桶子中
个位数为0:
个位数为1:81
个位数为2:22
个位数为3:73,93,143
个位数为4:14
个位数为5:55, 65
个位数为7:
个位数为8:28
个位数为9:139
第二步,将个元素按个位数排序的顺序依次放入序列,得到
81,22,73,93,143,14,55,65,28,139
第三步,将各个元素按照十位数排序放入不同桶子中并最后合并,得到:14, 22, 28, 139, 143, 55, 65, 73, 81, 93
第四步,依次按照百位、千位等等排序到最大数的最高位数得到最后的结果为:139,143, 14, 22, 28, 55, 65, 73, 81, 93

代码实现

#基数排序
import random
def radixSort(sequence):
    maxItemlength=len(str(max(sequence)))
    for i in range(maxItemlength):
        tempSequence=[[],[],[],[],[],[],[],[],[],[]]
        for item in sequence:
            temp=str(item)[-(i+1):-(i+2):-1]
            if temp == "":
                tempSequence[0].append(item)
            else:
                tempSequence[int(temp)].append(item)
        sequence=[j for tempItem in tempSequence for j in tempItem]
    return sequence
a_list=[]
for i in range(20):
    a_list.append(random.randint(1,1000))
print("排序前:",a_list)
print("排序后:",radixSort(a_list))

排序前: [952, 147, 830, 74, 47, 574, 750, 500, 504, 773, 700, 696, 561, 126, 290, 695, 811, 528, 655, 808]
排序后: [47, 74, 126, 147, 290, 500, 504, 528, 561, 574, 655, 695, 696, 700, 750, 773, 808, 811, 830, 952]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值