常见排序算法的的比较

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


1.冒泡排序

算法思想:
  冒泡排序的思想是,首先需要对整个列表A[:]进行操作,先把最大的数找出来,放到最后面,接着对A[:(n-1)]进行操作,把A[:(n-1)]中最大的数放到后面(A[:(n-1)]的最后面);接着对A[:(n-2)]进行操作。。。直到所有的数按照从小到大排列好。
  每一轮中,最大的数排到后面是通过冒泡来实现的。冒泡是指每次都比较相邻的两个数,把较大的数放到后面。注意这里的有两轮的比较,对应两层嵌套循环,第二层的嵌套循环是为了把最大的数放到最后,是通过冒泡实现的,图1显示了第一轮的冒泡过程;第一层循环是为了控制每次比较的列表长度。python代码如下:
  代码如下(示例):

def bublesort(a):
    n=len(a)
    for i in range(n-1,0,-1):
        for j in range(i):
            if a[j]>a[j+1]:
                a[j],a[j+1]=a[j+1],a[j]
a=[1,5,45,18,25,69,15,20]
bublesort(a)
print(a)

输出为:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201101200612814.png#pic_center:


图1:冒泡排序的第一次遍历

2. 选择排序

算法思想:
  从冒泡排序的算法思想可以看出来,在找最大值的时候,冒泡排序每次都只是比较相邻的两个数,通过一次次的比较和交换把最大的数找出来并且将他放到最后,这样做的效率比较低。选择排序在找最大值的时候,直接一次性把最大值找出来并将它当到最后。
代码如下(示例):

def selectionsort(a):
    n=len(a)
    for i in range(n-1,0,-1):
        #首先要找出当前数组的最大值的位置,然后将它和a[i]交换
        positionofmax=0
        for j in range(i+1):
            if a[j]>a[positionofmax]:
                positionofmax=j
        a[positionofmax],a[i]=a[i],a[positionofmax]
a=[1,5,45,18,25,69,15,20]
selectionsort(a)
print(a)
-------------------------------------------------------------------
输出为:
C:\Users\10989\anaconda3\python.exe C:/Users/10989/.PyCharm2017.1/config/scratches/selectionsort.py
[1, 5, 15, 18, 20, 25, 45, 69]

Process finished with exit code 0

3. 插入排序

算法思想:
  正如算法的名字所示, 插入排序是通过将数组中每个数字插入到它应该在的位置来完成的排序。其算法复杂度和冒泡排序,选择排序一样都是 O ( n 2 ) O(n^2) On2
  它总是保持一个位置靠前的已排好的子表,然后每一个新的数据项被“插入”到前边的子表里,排好的子表增加一项。图2显示了插入排序的过程。


图2:插入排序
  在选择排序中,我们开始认为只有一个数据项(position=0)的列表是一个拍好序的子列表。每次排序的时候,当前的数据项会与拍好序的子列表中的每个元素进行比较。当我们从当前项一步一步在子列表往回看的时候,我们每次把那些比右边大的数据项进行交换。当我们到达最小的数据项或者列表的起点时,就是当前数据项应该插入的位置。图3展示了第五次插入排序的具体操作。

图3:第五次插入排序的过程
  插入排序的代码如下:   
def insertion_sort(a_list):
    for index in range(1, len(a_list)):
        '''当前需要插入的项,将当前项从数组中拿出来,数组中的当前项位置为空'''
        current_value = a_list[index]
        '''position表示的是空白项的位置'''
        position = index
        '''我们需要空白项的左边的位置都比当前数据值要小'''
        '''如果空白项左边的位置比当前项大的话,可以将左边的位置移到右边,并将空白项的位置向前移'''
        while position > 0 and a_list[position - 1] > current_value:
            a_list[position] = a_list[position - 1]
            position = position - 1
        '''while循环结束表示找到应该放置空白项的位置,将当前值填入空白项'''
        a_list[position] = current_value


a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20]
insertion_sort(a_list)
print(a_list)
----------------------------------------------------------------------
输出为:
C:\Users\10989\anaconda3\python.exe C:/Users/10989/.PyCharm2017.1/config/scratches/insertionsort.py
[17, 20, 26, 31, 44, 54, 55, 77, 93]

Process finished with exit code 0

4. 希尔排序

        希尔排序是在插入排序的基础上进行的改进。它在插入排序的基础上,将原来要进行排序的列表划分成一些字列表,并对每个字列表进行插入排序。在希尔排序中,我们并不是将原始列表划分成一个连续的子列,而是确定了一个增量i来划分多个间隔为i的子列,并对这些子列来进行归并排序。

       图4展示了包含9个元素的列表的一种划分方法。列表的划分是以3为间隔。原始列表被划分成3个子列表,我们需要对三个子列表进行插入排序。


图4:以三维间隔的希尔排序

       插入排序的代码如下

def gap_insertionsort(a,start,gap):
    #gap为间隔i
    for i in range(start+gap,len(a),gap):
        current_value=a[i]
        position=i
        while position>=gap and a[position-gap]>current_value:
            a[position]=a[position-gap]
            position=position-gap
        a[position]=current_value

def shellsort(a):
    sublist_count=len(a)//2 #间隔距离为2
    while sublist_count>0:
        for start_position in range(sublist_count):
            gap_insertionsort(a,start_position,sublist_count)
        print("After increments of size", sublist_count, "The list is",a)
        sublist_count = sublist_count // 2

a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20]
shellsort(a_list)
print(a_list)
----------------------------------------------------------------------
输出为:
(base) C:\Users\10989\VScodeProject>C:/Users/10989/anaconda3/python.exe c:/Users/10989/VScodeProject/Hello/shellsort.py
After increments of size 4 The list is [20, 26, 44, 17, 54, 31, 93, 55, 77]
After increments of size 2 The list is [20, 17, 44, 26, 54, 31, 77, 55, 93]
After increments of size 1 The list is [17, 20, 26, 31, 44, 54, 55, 77, 93]
[17, 20, 26, 31, 44, 54, 55, 77, 93]

5.归并排序

        归并排序运用的是分治策略。它运用递归不断将原始列表一分为二,直到不能再分。接着对分出来的列表进行融合并比较大小,将较小的元素放在数组前面。图5展示了归并排序的拆分方法,图6展示了归并排序中的融合。


图5:归并排序中的分割

图6:归并排序中的融合展示

       归并排序的代码如下:注意每次递归结束后,会进行融合,融合之后得到的数组是一个已经排好序的子数组

def merge_sort(arr):
    if len(arr)>1:
        mid=len(arr)//2
        leftarr=arr[:mid]
        rightarr=arr[mid:]

        merge_sort(leftarr)
        merge_sort(rightarr)
        
        #初始化左,右数组的指针以及合并后的数组的指针
        i,j,k=0,0,0
        
        #比较左右数组的大小,较小的放到合并数组的前面
        #并将较小元素所在数组的指针后移
        while i < len(leftarr) and j < len(rightarr):
            if leftarr[i]<rightarr[j]:
                arr[k]=leftarr[i]
                i+=1
            else:
                arr[k]=rightarr[j]
                j+=1
            k+=1
        
        #当右边数组遍历完了,而左边数组没有遍历完的时候,直接把左边数组复制到arr上
        while i < len(leftarr):
            arr[k]=leftarr[i]
            i+=1
            k+=1
        
        #当左边数组遍历完了,而右边数组没有遍历完的时候,直接把右边数组复制到arr上
        while j < len(rightarr):
            arr[k]=rightarr[j]
            j+=1
            k+=1

a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20]
merge_sort(a_list)
print(a_list)
-------------------------------------------------------------------
输出为:
(base) C:\Users\10989\VScodeProject>C:/Users/10989/anaconda3/python.exe c:/Users/10989/VScodeProject/Hello/merge_sort.py
[17, 20, 26, 31, 44, 54, 55, 77, 93]

6. 快速排序

快速排序也是运用的分治算法的技巧,它不需要额外的空间,其时间复杂度在nlogn到 n 2 n^2 n2之间。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值