各种排序方法总结--基于python

最近在学数据结构里的排序,主要接触了冒泡排序,选择排序,插入排序,希尔排序,快速排序,基数排序还有堆积排序,然后用python语言写出了它们的具体实现方法,为了增强记忆,下面用自己最容易理解的语言再把它们总结一遍吧!

**—以下的各种排序算法我从是基于从小到大排序来进行的— **

1. 冒泡排序

冒泡排序就是从第一个元素开始,逐个比较与相邻元素的顺序,顺序不正确的话就对调,一直到最后一个元素。就像水里的泡泡咕噜咕噜上升到水面上一样…
比如一个无序数组:[9,8,7,66,55,4,3,2,1]
从第一个数9开始,比8大,不对,那就对调;这时第二个数是9了,和第三个数7比,不对,再对调。这样比下去的话,一个数只要比它前面的数大就会不停后移,一路比到最后,结果就是这个数组里最大的那个元素被送到了最后一位。我们要排序的这个数组一共9位数,第一个步骤后已经成功了1/9,emmmmm…
接下来最后一位我们不用管了,它已经是正确的了,再看前8位数吧,用上面同样的方式一路比下去,又顺利地把数组第二大的数送到了倒数第二个位置。好了,现在成功了2/9啦
这样一直重复下去,直至从后往前,每一个位置都被放上了正确的数字,排序完成
基于这个思路,写出python程序如下:

qq=[9,8,7,46,33,4,3,2,1]
print('初始排序是'+str(qq))
for i in range(int(len(qq)-1),-1,-1):
    for j in range(i):
        if qq[j]>qq[j+1]:
            qq[j],qq[j+1]=qq[j+1],qq[j]
    print('第'+str(len(qq)-i)+'次排序结果是:'+str(qq))
print('最终排序结果是'+str(qq))

但是有一个问题,比如我们要进行排序的数组是[1,2,3,5,4],第一轮就能使整个数组排序正确,但是上面的代码还是会继续循环3次才结束,后面就是再做无用功了,很没效率!怎么办

qq=[1,2,3,7,6]
print('初始顺序是:'+str(qq))
for i in range(len(qq)-1,-1,-1):
    flag=0
    for j in range(i):
        if qq[j]>qq[j+1]:
            qq[j],qq[j+1]=qq[j+1],qq[j]
            flag=flag+1
    if flag==0:
        break
    print('第'+str(len(qq)-i)+'次排序的结果是:'+str(qq))
#注意:print结果一定要放在break后面,否则还会多打印一轮冗余结果
print('最终的排序结果是'+str(qq))

基于前面的代码,加了一个flag,每一轮循环完如果flag仍然是0,说明这一轮循环并没有做任何改变,说明数组已经被正确排序了,那就可以终止循环得到最终结果

总结:冒泡排序是从后往前依次放入正确排序的元素

2.选择排序

我感觉选择排序和冒泡排序的思路正好相反,先选择最小的数放在第一个位置,然后选择第二小的数放在第二个位置,这样依次重复下去直至得到排序好的数组…
具体是这样的:还是从第一个元素开始,让它分别跟后面的所有元素作比较,如果大于谁了,就把谁给换到第一个位置来,这样比完一轮的结果是最小的元素成功被放到了第一个位置
下面再从第二个位置开始,也是同样的思路,比完一轮后第二小的元素被放到了第二个位置
按照同样的方式一直到倒数第二个元素也比完了,这样整个数组都被排序好了

qq=[9,8,7,66,55,4,3,2,1]
print('原始排列是'+str(qq))
for i in range(len(qq)-1):
    for j in range(i+1,len(qq)):
        if qq[i]>qq[j]:
            qq[i],qq[j]=qq[j],qq[i]
    print('这次排序后变为:'+str(qq))
print('--------------------------------------------------')
print('最终排序结果是:'+str(qq))

我当时也在想改进版的选择排序,用了上面冒泡排序一样的flag标记法,后来一想不对啊!冒泡排序是从前到后每一个都比,所以只要某一轮的flag为0则说明数列是正确顺序排列的,但是选择排序的某一轮flag为0只能说明这个元素被放在了正确的位置,后面的元素不一定呀

(我过了一小时来看我上面这段话,发现我不知道自己在说啥了…就这样吧)

总结:选择排序是从前往后依次把正确的元素放在指定位置

3.插入排序

插入排序的思路是这样的,先排好前2个元素,再把第三个元素插到正确的位置,这样前三个元素都是正确排序的了,再把第四个元素插到正确的位置…这样重复下去直至所有元素都被插入到了正确的位置
具体这样:先比较前两个元素,很好操作,位置对了就保持原样,不对的对调位置
然后看第三个元素,先让它跟第二个比,如果比第二个大,不用再和第一个元素比了,因为前两个元素已经是排列好的了,比第二个都大了肯定也比第一个大,那么第三个元素就不用动;如果比第二个小,那就再和第一个比,比第一个大就把第三个元素放到一二元素之间,比第一个小就放在第一个元素前面
下面来看第k个元素,先和第k-1个比,一直推进。如果比谁小,就继续往前比,一直到遇到比自己小的,就把自己放在它后面,如果很不幸,比到头了都没遇到比自己小的,那就把自己放在第一个位置

qq=[9,8,7,66,55,4,3,2,1]
print('初始顺序是:'+str(qq))
for i in range(1,len(qq)):
    tem=qq[i]
    no=i-1
    while no>=0 and tem<qq[no]:
        qq[no+1]=qq[no]
        no=no-1
    qq[no+1]=tem
    print('这次排序完的结果是:'+str(qq))
print('----------------------------------------------------------')
print('最终排序结果是:'+str(qq))

说的容易,插到谁后面,但是用python的数组的话就很麻烦,后面的每个数都得后移一个位置。用python的链表结构应该会方便点,下次可以试试

4.希尔排序

我把希尔排序看作是插入排序plus版,更加快捷的排序方式
插入排序的每个元素插入时,是逐个往前比的,但是希尔排序先给元素分组,再用插入排序比,不用逐个比,只要往前比固定间隔的元素即可。然后不断减小间隔,直到最终每个元素都是独立的个体
为了方便就先二分再四分再八分一直到分完吧…

data=[9,8,7,66,55,4,3,2]
print('原始顺序是:'+str(data))
s=len(data)
d=s//2
while d!=0:
    for i in range(d,s):
        te=data[i]
        j=i-d
        while j>=0 and te<data[j] :
            data[j+d]=data[j]
            j=j-d
        data[j+d]=te
        print('这次的排序结果是:'+str(data))
    d=d//2
print('-------------------------------------------------')
print('最终的排序结果是:'+str(data))

5.快速排序

快排是最重要的一种排序方式,也是公认的最佳排序?思路是先随便找一个数,然后把小于它的放它左边,大于它的放它右边,再以同样的方式处理它左右的元素,一直到排序完成
看起来好像很容易,但是python实现真的好复杂啊,我感觉好难,看了好久才弄明白,而且我估摸着过几天我又看不懂了自己在写啥了

def quick(d,size,lf,rg):
    #第一项键值为d[lf]
    if lf<rg:  #排序数列的左边与右边
        lf_idx=lf+1
        while d[lf_idx]<d[lf]:
            if lf_idx+1 >size:
                break
            lf_idx +=1
        rg_idx=rg 
        while d[rg_idx] >d[lf]:
            rg_idx -=1
        while lf_idx<rg_idx:
            d[lf_idx],d[rg_idx]=d[rg_idx],d[lf_idx]
            lf_idx +=1
            while d[lf_idx]<d[lf]:
                lf_idx +=1
            rg_idx -=1
            while d[rg_idx] >d[lf]:
                rg_idx -=1
        d[lf],d[rg_idx]=d[rg_idx],d[lf]

        for i in range(size):
            print('%3d' %d[i],end='')
        print()
       
        quick(d,size,lf,rg_idx-1)   #以rg_idx为基准点分成左右两半以递归方式
        quick(d,size,rg_idx+1,rg)   #分别为左右两半进行排序直至完成排序        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值