引言
首先是排序算法,总的来说也挺多的如冒泡,选择,快速排序等等.但有的只是说锻炼一下你的写代码能力,在实际的应用中用他就是傻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(尾结点),不过也好搞,就不改了
下面是链表的实现思想是一样的
在这里插入代码片