python_查找排序算法汇总_2021.6.8

引言


首先是排序算法,总的来说也挺多的如冒泡,选择,快速排序等等.但有的只是说锻炼一下你的写代码能力,在实际的应用中用他就是傻B,而快速排序是很快的一种排序方法,平均时间复杂度可以达到o(nlogn)还是很不错的.最快的应该是二叉排序树的中序遍历,但需要去转化成某一种数据结构,涉及到转化时还是挺烦人的,堆排序也不错,就一直出堆就行了

冒泡排序

					两个循环嵌套的写法
import random
import time
sta=time.time()
#定义冒泡排序函数
def maopao(_list):
    #首先是一个大循环  有多少个数据,有多少次大的循环
    for i in range(len(_list)):
        for j in range(1,len(_list)-i):
            if _list[j-1]>_list[j]:
                #交换位置
                _list[j-1],_list[j]=_list[j],_list[j-1]
    return _list


for j in range(100):
    _list = []
    for i in range(random.randint(100,1000)):   #循环10到15次
        _list.append(random.randint(1,1000000))
    print(maopao(_list))
print(time.time()-sta)

运行了大概3.64

这个是用链表写的,主要是锻炼一下写代码的能力,因为每次多了些判断所以时间需要的更多,也可以拿个变量像列表一样记录他的长度,应该会减少一些复杂度

import random
import time
sta=time.time()
#定义链表类
class node():
    def __init__(self,item,next=None):
        self.item=item
        self.next=next
#定义冒泡排序函数
def maopao(head,tail):
    #试一下链式存储的冒泡排序
    while head!=tail:
        t=head
        while t :
            if t.item>t.next.item:
                t.item,t.next.item=t.next.item,t.item
            if t.next!=tail:
                t=t.next
            else:
                break
        tail=t
    return head
for j in range(100):
    head=node(0)
    #为了尾部添加元素而创建
    tail=head
    for i in range(random.randint(100,1000)):   #循环10到15次
        p=node(random.randint(1,1000000))
        tail.next=p
        tail=p
    head=head.next
    print(maopao(head,tail))
print(time.time()-sta)

上面都是是冒泡排序的经典写法就是锻炼一下写代码的能力

选择排序要比冒泡排序好一些,毕竟不需要每次都换位置,他也是两层循环嵌套
下面是代码

import random
import time
sta=time.time()
def xuanze(_list):
    for i in range(len(_list)):
        max=0
        for j in range(1,len(_list)-i):
            if _list[max]<_list[j]:
                #小一些记录
                max=j
        #出来的时候的j一定是可以达到的最后一位,将最大的放在后面
        _list[max],_list[len(_list)-i-1]=_list[len(_list)-i-1],_list[max]

    return _list
for j in range(100):
    _list = []
    for i in range(random.randint(100,1000)):   #循环10到15次
        _list.append(random.randint(1,1000000))
    xuanze(_list)
    print(_list)
print(time.time()-sta)  时间2.004956007003784确实好一些

下面这个代码是最开始的有问题代码

import random
import time
sta=time.time()
def xuanze(_list):
    for i in range(len(_list)):
        max=0
        for j in range(1,len(_list)-i):
            if _list[max]<_list[j]:
                #小一些记录
                max=j
        #出来的时候的j一定是可以达到的最后一位,将最大的放在后面
        _list[max],_list[j]=_list[j],_list[max]

    return _list
for j in range(100):
    _list = []
    for i in range(random.randint(100,1000)):   #循环10到15次
        _list.append(random.randint(1,1000000))
    xuanze(_list)
    print(_list)
print(time.time()-sta)

一部分输出结果
[61671, 50634, 172529, 183086, 387244, 734928, 735955, 781295, 828766, 951251]
[27941, 14748, 106985, 302952, 419142, 732814, 736612, 881138, 887536, 977384]
[223719, 44377, 244612, 437533, 481092, 494602, 576404, 576896, 602885, 894510]
[191541, 158667, 288551, 302948, 423753, 437692, 541241, 724504, 745217, 979144]
可以看到前两位每次都是这个样子,那么是哪里出错了呢,
假如说len(_list)==10,那么当i=9的时候是进不去第二个
循环的那么j的值仍然为上一个循环结束时j的值是多少,1,所以
又一次的换了位置

这个是选择排序的链表代码

import random
import time
sta=time.time()
#定义链表类
class node():
    def __init__(self,item,next=None):
        self.item=item
        self.next=next
#链表实现
def xuanze(head,tail):
    #这个要保存的是最大值对应的节点
    while head!=tail:
        t=head
        max=t
        while t:
            #t不为空进来
            if max.item<t.item:   #最大的与当前作比较
                max=t
            if t.next!=tail:
                t=t.next
            else:
                break
        #出来的时候tail的item与max没有比较
        if max.item<tail.item:
            #如果真的是这样说明当前未排序尾部的值是最大的,不需要动
            max=tail
        else:
            max.item,tail.item=tail.item,max.item
        tail=t
    return head

for j in range(100):
    head=node(0)
    #为了尾部添加元素而创建
    tail=head
    for i in range(random.randint(100,1000)):   #循环10到15次
        p=node(random.randint(1,1000000))
        tail.next=p
        tail=p
    head=head.next
    head=xuanze(head,tail)
    while head:
        print(head.item,end=',')
        head=head.next
    print()
print(time.time()-sta)

插入排序
这玩意的思想和前面的选择,冒泡不一样.它有点像打扑克牌的时候,你从左往右看找到合适的牌进行插入.

下面是它每一次的步骤
在这里插入图片描述
这是他的代码,就是比大小如果current小一些,就向后移一位把位置空出来

import random
import time
sta=time.time()
#插入排序是从左往右的看,一个一个的往后移
def charu(_list):
    for i in range(1,len(_list)):  #从第二位开始到结束
        #获得当前索引对应的值
        current=_list[i]  #数据已经被保存,相当于索引i处的值空了出来
        position=i  #获得当前节点位置
        while position>0 and _list[position-1]>current:
            #能进来说明当前节点的上一个比他大
            #需要向后移
            _list[position]=_list[position-1]
            position-=1
        _list[position]=current
    return _list
for j in range(100):
    _list=[]
    for i in range(random.randint(100,1000)):
        _list.append(random.randint(1,1000000))
    print(charu(_list))
print(time.time()-sta)  时间花费2.9

下面是链表的写法
因为每一次的当前数据会和他的上一个数据进行比较,所以需要化成双链表的形式

import random
import time
sta=time.time()

class Node():
    def __init__(self,item,next=None,parent=None):
        self.item=item
        self.next=next
        self.parent=parent

def charu(head):
    if head==None:
        return None
    #真正循环结束一定是当前节点为最后一个节点
    #最开始的时候将第二个节点设为最后的
    tail=head.next
    while tail:
        t=tail
        #保存当前节点对应数据
        current=t.item
        while t.parent and t.parent.item>current:
            #能进来说明t不是头节点 且对应的值要大一些,往后移
            t.item=t.parent.item
            #当前位置前移
            t=t.parent
        #出来的时候当前t对应的数据已经后移了这个位置已经空出来了
        t.item=current
        tail=tail.next
    return head


for j in range(100):
    head=Node(0)
    tail=head
    for i in range(random.randint(100,1000)):
        #创建一个对象
        p=Node(random.randint(1,1000000))
        #双链表的链接
        tail.next=p
        p.parent=tail
        tail=p
    head=head.next
    head=charu(head)
    while head:
        print(head.item,end=',')
        head=head.next
    print()
print(time.time()-sta)   哈哈哈测试的时候吓死我了跑了1.8秒今天再测终于正常了,应该是昨天机缘巧合下数据适合查找算法跑

快速排序
在这里插入图片描述
我这种写法.列表中是可能没有数据是一个空列表,这需要考虑到,中值的话
我才用的是每次取第一个作为中值,不去考虑为找到中位数花费时间.
在这里插入图片描述
在这里插入图片描述
上面放了几张图为了以后逻辑方便点

#快速排序的主要思路是说找到你一个中值,你可以是花一定开销去找
#也可以任意去一个当作中值
#下面就是不断的将比中值小的放在左边
#比中值大的放在右边,然后调用自身再次执行
import random
import time
sta=time.time()
def kuaipai(_list):
    if _list==[]:
        return []
    if len(_list)==1:
        return _list
    #1.先赋值左右
    left=1
    right=len(_list)-1
    #2.取中值,直接以首位作为中值
    zhongzhi=_list[0]
    done=True
    #3.进行循环
    while done:
        #内层循环首先是左边
        while left<=right and _list[left]<=zhongzhi:
            #第一个条件是确保left不会超出列表长度
            #第二个条件是说进来的时候没有找到心意的对象
            #大于中值都可以让他停下来
            left+=1
        #右边
        while left<=right and _list[right]>=zhongzhi:
            #第一个条件是确保right不会超出列表长度
            #第二个条件是说进来的时候没有找到心意的对象
            #小于中值的都可以让他停下来
            right-=1
        #当两个循环都出来的时候
        #这个时候的他俩是有可能变成下面这个样子
        if left>right:
            #这个时候最外层循环就可以停止了
            done=False
        else:
            #现在需要换位置
            _list[left],_list[right]=_list[right],_list[left]
    #最后right的位置好像就是中值的位置
    _list[right],_list[0]=_list[0],_list[right]
    return kuaipai(_list[:right:])+[_list[right]]+kuaipai(_list[right+1::])

for j in range(1000):
    _list=[]
    for i in range(random.randint(100, 1000)):
        _list.append(random.randint(1, 1000000))
    print(kuaipai(_list))
print(time.time()-sta)   时间花费1.032677173614502

这玩意是挺快的

快速排序还是需要用双链表去实现,主要的问题是我上面写的链表代码好像不具有通用性,我为了省减少一些时间花费,要求传参的时候必须传tail(尾结点),不过也好搞,就不改了

下面是链表的实现思想是一样的

在这里插入代码片
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值