排序算法demo

排序算法有段时间没看了,之前一直用伪码,尝试用python写下
文章最后有自己当初总结的快速记住各排序算法的时间复杂度空间复杂度稳定性适用场景的小口诀

冒泡排序法demo(Buddle Sort)

def bubble (data):
    for i in range(7,-1,-1): # 扫描次数
        for j in range(i):
            if data[j]>data[j+1]:#比较,交换的次数
                data[j],data[j+1]=data[j+1],data[j] # 不使用临时变量,把临近两数中最小的置为前面
        print('第 %d 次排序后的结果是:' %(8-i),end='') #把各次扫描后的结果打印出来
        for j in range(8):
            print('%3d' %data[j],end='')
        print()

def showdata(data):
    for i in range(8):
        print('%3d'%data[i],end='')

def main():
    data = [16, 25, 39, 27, 12, 8, 45, 63]  # 原始数据
    print('冒泡排序法的原始数据为:')
    showdata(data)
    print()
    bubble(data)
    print('排序后的结果: ')
    showdata(data)

main()

打印数据为

冒泡排序法的原始数据为:
 16 25 39 27 12  8 45 631 次排序后的结果是: 16 25 27 12  8 39 45 632 次排序后的结果是: 16 25 12  8 27 39 45 633 次排序后的结果是: 16 12  8 25 27 39 45 634 次排序后的结果是: 12  8 16 25 27 39 45 635 次排序后的结果是:  8 12 16 25 27 39 45 636 次排序后的结果是:  8 12 16 25 27 39 45 637 次排序后的结果是:  8 12 16 25 27 39 45 638 次排序后的结果是:  8 12 16 25 27 39 45 63
排序后的结果: 
  8 12 16 25 27 39 45 63

冒泡排序花费时间主要集中在固定循环n-1次的两两比较,使用岗哨来提前中断程序

def bubble (data):
    for i in range(7,-1,-1):
        flag=0    #flag用来判断是否执行了交换操作
        for j in range(i):
            if data[j+1]<data[j]:
                data[j],data[j+1]=data[j+1],data[j]
                flag+=1  #如果执行过交换操作,则flag不为0
        if flag==0:
            break
        # 当执行完一次扫描就判断是否执行过交换操作,如果没有交换过数据,
	    # 表示此时数组已完成排序,故可直接跳出循环
        print('第%d次排序'%(8-i),end='')
        for j in range(8):
            print('%3d' %data[j],end='')
        print()

def showdata(data):    #使用循环打印数据
    for i in range(8):
        print('%3d' %data[i],end='')
    print()

def main():
    data=[16,25,39,27,12,8,45,63]  #原始数据
    print('使用岗哨的冒泡排序法测试用的原始数据为:')
    showdata(data)
    bubble(data)
    print('排序后的结果为:',end='')
    showdata(data)
    
main()

打印数据为

使用岗哨的冒泡排序法测试用的原始数据为:
 16 25 39 27 12  8 45 631次排序 16 25 27 12  8 39 45 632次排序 16 25 12  8 27 39 45 633次排序 16 12  8 25 27 39 45 634次排序 12  8 16 25 27 39 45 635次排序  8 12 16 25 27 39 45 63
排序后的结果为:  8 12 16 25 27 39 45 63

选择排序demo(Selection Sort)

def select (data):
    for i in range(7): # 只插前7个
        for j in range(i+1,8):  # 下标值
            if data[i]>data[j]: # 取第i个位置的最大值(不包括小于i的数)
                data[i],data[j]=data[j],data[i]
        print('第%d次排序' % (8 - i), end='')
        for j in range(8):
            print('%3d' % data[j], end='')
        print()

def showdata (data):
    for i in range(8):
        print('%3d' %data[i],end='')
    print()

def main():
    data=[16,25,39,27,12,8,45,63]
    print('原始数据为:')
    showdata(data)
    select(data)
    print("排序后的数据为:")
    showdata(data)

main()

打印结果

原始数据为:
 16 25 39 27 12  8 45 638次排序  8 25 39 27 16 12 45 637次排序  8 12 39 27 25 16 45 636次排序  8 12 16 39 27 25 45 635次排序  8 12 16 25 39 27 45 634次排序  8 12 16 25 27 39 45 633次排序  8 12 16 25 27 39 45 632次排序  8 12 16 25 27 39 45 63
排序后的数据为:
  8 12 16 25 27 39 45 63

插入排序(InsertSort)

def insert(data):
    for i in range(1,8): # i作下标
        tmp=data[i] #tmp临时变量,暂定其为最小
        no=i-1
        while no>=0 and tmp<data[no]:
            data[no+1]=data[no]	# 决定了其适合链表,左参数右值,小→大,右移
            no-=1
        data[no+1]=tmp #最小的元素放到第一个位置
        print('第%d次排序' % (i), end='')
        for j in range(8):
            print('%3d' % data[j], end='')
        print()

def showdata(data):
    for i in range(8):
        print('%3d' %data[i],end='')   #打印数组数据
    print()

def main():
    data=[16,25,39,27,12,8,45,63]
    print('原始数组是:')
    showdata(data)
    insert(data)
    print('排序后的数组是:')
    showdata(data)

main()

打印结果

原始数组是:
 16 25 39 27 12  8 45 631次排序 16 25 39 27 12  8 45 632次排序 16 25 39 27 12  8 45 633次排序 16 25 27 39 12  8 45 634次排序 12 16 25 27 39  8 45 635次排序  8 12 16 25 27 39 45 636次排序  8 12 16 25 27 39 45 637次排序  8 12 16 25 27 39 45 63
排序后的数组是:
  8 12 16 25 27 39 45 63

希尔排序(Shell Sort)

# 随着间距值越来越小,局部有序度在不断提高,最后插排所花费的开销就小了
def shell(data,size):
    k=1 #k打印计数
    jmp=size//2  # " // "表示整数除法。jmp既是划分出的组数,也是间距值
    while jmp != 0:
        for i in range(jmp, size):  # i为扫描次数 jmp 为设置间距的位移量
            tmp=data[i]  #tmp用来暂存数据
            j=i-jmp      #以j来定位比较的元素
            while tmp<data[j] and j>=0:  #插入排序法
                data[j+jmp] = data[j] # 往后挪jmp位
                j=j-jmp
            data[jmp+j]=tmp # 第j位补交换值
        print('第 %d 次排序过程:' %k,end='')
        k+=1
        showdata (data)
        jmp=jmp//2    #控制循环数

def showdata(data):
    for i in range(8):
        print('%3d' %data[i],end='')
    print()

def main():
    data=[16,25,39,27,12,8,45,63]
    print('原始数组是:')
    showdata (data)
    shell(data,8)
    print('排序后的结果为:')
    showdata(data)

main()

打印结果:

原始数组是:
 16 25 39 27 12  8 45 631 次排序过程: 12  8 39 27 16 25 45 632 次排序过程: 12  8 16 25 39 27 45 633 次排序过程:  8 12 16 25 27 39 45 63
排序后的结果为:
  8 12 16 25 27 39 45 63

归并排序法(Merge Sort)

# 合并排序法(Merge Sort)

#99999为数列1的结束数字不列入排序
list1 = [20,45,51,88,99999]
#99999为数列2的结束数字不列入排序
list2 = [98,10,23,15,99999] 
list3 = []

def merge_sort():
    global list1
    global list2
    global list3
        
    # 先使用选择排序将两个数列排序,再进行合并
    select_sort(list1, len(list1)-1)
    select_sort(list2, len(list2)-1)

    
    print('第1个数列的排序结果为: ', end = '')
    for i in range(len(list1)-1):
        print(list1[i], ' ', end = '')

    print('\n第2个数列的排序结果为: ', end = '')
    for i in range(len(list2)-1):
        print(list2[i], ' ', end = '')
    print()

    print('=' * 50)
    My_Merge(len(list1)-1, len(list2)-1)
    print()
    print('=' * 50)
    print()

    print('合并排序法的最终结果为: ', end = '')
    for i in range(len(list1)+len(list2)-2):
        print('%d ' % list3[i], end = '')
        
def select_sort(data, size):
    for i in range(size-1): #
        temp = i
        for j in range(i+1, size):
            if data[j] < data[temp]:
                temp = j
        data[temp], data[i] = data[i], data[temp]

def My_Merge(size1, size2):
    global list1
    global list2
    global list3

    index1 = 0
    index2 = 0
    for index3 in range(len(list1)+len(list2)-2):
        if list1[index1] < list2[index2]: # 比较两个数列,数小的先存于合并后的数列
            list3.append(list1[index1])
            index1 += 1
            print('\n此数字%d取自于第1个数列' % list3[index3])
        else:
            list3.append(list2[index2])  #新数列赋值
            index2 += 1                  #原数列下标
            print('\n此数字%d取自于第2个数列' % list3[index3])
        print('目前的合并排序结果为: ', end = '')
        for i in range(index3+1):
            print(list3[i], ' ', end = '')

merge_sort()

打印结果

1个数列的排序结果为: 20  45  51  882个数列的排序结果为: 10  15  23  98  
==================================================

此数字10取自于第2个数列
目前的合并排序结果为: 10  
此数字15取自于第2个数列
目前的合并排序结果为: 10  15  
此数字20取自于第1个数列
目前的合并排序结果为: 10  15  20  
此数字23取自于第2个数列
目前的合并排序结果为: 10  15  20  23  
此数字45取自于第1个数列
目前的合并排序结果为: 10  15  20  23  45  
此数字51取自于第1个数列
目前的合并排序结果为: 10  15  20  23  45  51  
此数字88取自于第1个数列
目前的合并排序结果为: 10  15  20  23  45  51  88  
此数字98取自于第2个数列
目前的合并排序结果为: 10  15  20  23  45  51  88  98  
==================================================

合并排序法的最终结果为: 10 15 20 23 45 51 88 98 

快速排序法(QuickSort)

import random

def inputarr(data,size):
    for i in range(size):
        data[i]=random.randint(1,100)  # 生成指定的(1,100)的随机整数
        
def showdata(data,size):
    for i in range(size):
        print('%3d' %data[i],end='')
    print()

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)   #分别为左右两半进行排序直至完成排序               
		
def main():
    data=[0]*100 # 初始化
    size=int(input('请输入数组大小(100以下):'))
    inputarr (data,size)
    print('您输入的原始数据是:')
    showdata (data,size)
    print('排序过程如下:')
    quick(data,size,0,size-1)
    print('最终的排序结果为:')
    showdata(data,size)

main()

输出结果

请输入数组大小(100以下)12
您输入的原始数据是:
 83 67 32 88 88 50 35 13 35 40  4 14
排序过程如下:
 40 67 32 14  4 50 35 13 35 83 88 88
 35 35 32 14  4 13 40 50 67 83 88 88
  4 13 32 14 35 35 40 50 67 83 88 88
  4 13 32 14 35 35 40 50 67 83 88 88
  4 13 32 14 35 35 40 50 67 83 88 88
  4 13 14 32 35 35 40 50 67 83 88 88
  4 13 14 32 35 35 40 50 67 83 88 88
  4 13 14 32 35 35 40 50 67 83 88 88
最终的排序结果为:
  4 13 14 32 35 35 40 50 67 83 88 88

堆排序(HeapSort)

def heap(data,size):
    for i in range(int(size/2),0,-1):#建立堆积树节点
        ad_heap(data,i,size-1)
    print()
    print('堆积的内容:',end='')
    showdata(data,size)
    print()
    print("=="*30)
    for i in range(size-2,0,-1): #堆积排序
        data[i+1],data[1]=data[1],data[i+1]#头尾节点交换
        ad_heap(data,1,i)#处理剩余节点
        print('处理过程为:',end='')
        showdata(data,size)
        print()

def ad_heap(data,i,size):
    j=2*i
    tmp=data[i]
    post=0
    while j<=size and post==0:
        if j<size:
            if data[j]<data[j+1]: #找出最大节点
                j+=1
        if tmp>=data[j]: #若树根较大,结束比较过程
            post=1
        else:
            data[int(j/2)]=data[j]#若树根较小,则继续比较
            j=2*j
    data[int(j/2)]=tmp #指定树根为父节点

def main():
    data=[0,5,6,4,8,3,2,7,1]	#原始数组的内容
    size=9
    print('原始数组为:',end='')
    showdata(data,size)
    heap(data,size) #建立堆积树
    print("=="*30)
    print('排序结果为:',end='')
    showdata(data,size)

def showdata(data,size):
    for i in range(1,size):
        print('[%d] ' %data[i],end='')
main()

打印结果为:

原始数组为:[5] [6] [4] [8] [3] [2] [7] [1] 
堆积的内容:[8] [6] [7] [5] [3] [2] [4] [1] 
============================================================
处理过程为:[7] [6] [4] [5] [3] [2] [1] [8] 
处理过程为:[6] [5] [4] [1] [3] [2] [7] [8] 
处理过程为:[5] [3] [4] [1] [2] [6] [7] [8] 
处理过程为:[4] [3] [2] [1] [5] [6] [7] [8] 
处理过程为:[3] [1] [2] [4] [5] [6] [7] [8] 
处理过程为:[2] [1] [3] [4] [5] [6] [7] [8] 
处理过程为:[1] [2] [3] [4] [5] [6] [7] [8] 
============================================================
排序结果为:[1] [2] [3] [4] [5] [6] [7] [8] 

基数排序(Radix Sort)

# 基数排序法:从小到大排序
import random

def inputarr(data,size):
    for i in range(size):
        data[i]=random.randint(0,999) #设置 data 值最大为 3 位数

def showdata(data,size):
    for i in range(size):
        print('%5d' %data[i],end='')
    print()

def radix(data,size): 
     n=1 # n为基数,从LSD
     while n<=100:
        tmp=[[0]*100 for row in range(10)] # 设置暂存数组,[0~9位数][数据个数],所有内容均为0
        for i in range(size):    # 对比所有数据
            m=(data[i]//n)%10    # m为 n 位数的值,如 36 取十位数(36/10)%10=3
            tmp[m][i]=data[i]    # 把 data[i] 的值暂存在 tmp 中
        k=0
        for i in range(10):
            for j in range(size):
                if tmp[i][j] != 0:    # 因为一开始设置 tmp ={0},故不为 0 者即为
                    data[k]=tmp[i][j] # data 暂存在 tmp 中的值,把 tmp 中的值放
                    k+=1              # 回 data[ ]里
        print('经过%3d位数排序后:' %n,end='')
        showdata(data,size)
        n=10*n

def main():
    data=[0]*100
    size=int(input('请输入数组大小(100以下):'))
    print('您输入的原始数据是:')
    inputarr (data,size)
    showdata (data,size)
    radix (data,size)

main()

打印结果

请输入数组大小(100以下)15
您输入的原始数据是:
   27  208  329  899  988   23   23  283  820  681  630  922  925  753   71
经过  1位数排序后:  820  630  681   71  922   23   23  283  753  925   27  208  988  329  899
经过 10位数排序后:  208  820  922   23   23  925   27  329  630  753   71  681  283  988  899
经过100位数排序后:   23   23   27   71  208  283  329  630  681  753  820  899  922  925  988

在这里插入图片描述

  1. 不稳定算法: 快些选一堆(快排、shell、选择排序、堆排),除此以外全是稳定性算法
  2. 选择交换,插入后移
  3. 最好时间复杂度(有序):直插冒泡
  4. 时间复杂度O(nlogn):快堆并
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值