首页 > 编程语言 >【数据结构和算法】排序算法

【数据结构和算法】排序算法

时间:2023-12-06 17:22:39浏览次数:39  
标签:排序 copyBuffer 列表 算法 swap 数据结构 lyst def

使用swap函数来交换列表中的两项的位置

1 def swap(lyst,i,j):
2     '''交换列表中两项的位置'''
3     temp = lyst[i]
4     lyst[i] = lyst[j]
5     lyst[j] = temp

① 选择排序

处于列表第一项,先找到最小项的位置,如果该位置不是列表的第一项,算法会交换这两个位置的项,然后算法回到第二项并重复上述过程,如果第二项比最小值要大,则交换位置,当算法到列表最后的位置时,列表排序好了

 1 def swap(lyst,i,j):
 2     '''交换列表中两项的位置'''
 3     temp = lyst[i]
 4     lyst[i] = lyst[j]
 5     lyst[j] = temp
 6 
 7 def selectionSort(lyst):
 8     i = 0
 9     while i < len(lyst): #Do n -1 searches
10         minIndex = i     #for the smallest
11         j = i + 1
12         while j < len(lyst):  #start a search
13             if lyst[j] < lyst[minIndex]:
14                 minIndex = j
15             j = j + 1
16         if minIndex != i:
17             swap(lyst,minIndex,i)
18 
19         i += 1

② 冒泡排序

从列表得开头处开始,比较相邻两项,每当左边的比右边的时,算法就交换其位置,这样效果就将最大项以冒泡的方式排到列表末尾,然后算法从列表开头到倒数第二项重复上述过程。

 1 def swap(lyst,i,j):
 2     '''交换列表中两项的位置'''
 3     temp = lyst[i]
 4     lyst[i] = lyst[j]
 5     lyst[j] = temp
 6 
 7 def bubbleSort(lyst):
 8     n = len(lyst):
 9     while n > 1:      #Do n-1 bubble
10         i = 1         #start each bubble    
11         while i < n :
12             if lyst[i] < lyst[i-1]: #exchange if needed
13                 swap(lyst,i,i-1)
14             i += 1
15         n -= 1

在最好的情况下,第一轮发生已经排序好了

 1 def swap(lyst,i,j):
 2     '''交换列表中两项的位置'''
 3     temp = lyst[i]
 4     lyst[i] = lyst[j]
 5     lyst[j] = temp
 6 
 7 def bubbleSort(lyst):
 8     n = len(lyst):
 9     while n > 1:      #Do n-1 bubble
10     swapped = False
11         i = 1         #start each bubble    
12         while i < n :
13             if lyst[i] < lyst[i-1]: #exchange if needed
14                 swap(lyst,i,i-1)
15                 swapped = True
16             i += 1
17         if not swapped:return   #return if no swaps
18         n -= 1 

③ 插入排序

类似扑克牌的顺序,如果按照顺序放好了i-1张牌,对于抓取第i张牌,将其手中的这些牌进行比较,知道找到合适的位置

第i轮之后,前i项应该是排好序的

 1 def insertionSort(lyst):
 2     i = 1
 3     while i < len(lyst):
 4         itemToInsert = lyst[i]
 5         j = i - 1
 6         while j >= 0:
 7             if itemToInsert < lyst[j]:
 8                 lyst[j + 1] = lyst[j]
 9                 j -= 1
10             else:
11                 break
12         lyst[j + 1] = itemToInsert
13         i += 1

 阶段总结:

1.冒泡排序在最好情况下(列表已经排好序)性能为O(n),在最好的情况下是O(n^2),平均情况下性能更接近于O(n^2)

2.插入排序在最好情况下(列表有序)性能为O(n),最坏情况下复杂度为O(n^2),平均情况下也是O(n^2)

3.选择排序在各种情况下的排序都为O(n^2)

④ 快速排序

1.找到基准点,将大于基准点的项放在一个子列表,小于基准点的项放在一个子列表

2.对上述子列表重复上述过程

在最坏的情况下,快速排序算法的性能是O(n^2)  -->>>>>每一次基准值都取第一个

一般请款修改,快速排序算法的性能是O(nlog2^n) ->>>>>>>每一次都从中间取基准值

每次递归调用都需要固定大小的内存用于栈,并且在每一次分割之后都有两次递归调用,因此在最好的情况下,内存使用是O(log2^n),最坏的情况下,内存是O(n)

实现:

 1 def swap(lyst,i,j):
 2     '''交换列表中两项的位置'''
 3     temp = lyst[i]
 4     lyst[i] = lyst[j]
 5     lyst[j] = temp
 6 
 7 def quicksort(lyst):
 8     quicksortHelper(lyst, 0, len(lyst) - 1)
 9 
10 def quicksortHelper(lyst, left, right):
11     if left < right:
12         pivotLocation = partition(lyst, left, right)
13         quicksortHelper(lyst, left, pivotLocation - 1)
14         quicksortHelper(lyst, pivotLocation + 1, right)
15 
16 def partition(lyst, left, right):
17     # 找到基准值,并与最后一项进行交换
18     middle = (left + right) // 2
19     pivot = lyst[middle]
20     lyst[middle] = lyst[right]
21     lyst[right] = pivot
22     # 将最左边的点设置边界
23     boundary = left
24     # 将小于基准值的项移到边界的左边
25     for index in range(left,right):
26         if lyst[index] < pivot:
27             swap(lyst, index, boundary)
28             boundary += 1
29     # 将边界点与基准值点进行交换
30     swap(lyst, right, boundary)
31     return boundary
32 
33 import random
34 
35 def main(size=20, sort=quicksort):
36     lyst = []
37     for count in range(size):
38         while len(lyst) < 20:
39             num = random.randint(1,size + 1)
40             if num not in lyst:
41                 lyst.append(num)
42     print(lyst)
43     sort(lyst)
44     print(lyst)
45 
46 if __name__ == '__main__':
47     main()

④ 合并排序

合并排序利用了递归,分而治之的策略来突破O(n^2)的障碍

 

 1 import random
 2 import array
 3 
 4 def mergeSort(lyst):
 5     copyBuffer = array.array('b')
 6     mergeSortHelper(lyst, copyBuffer, 0, len(lyst) - 1)
 7 
 8 def mergeSortHelper(lyst, copyBuffer, low, high):
 9     if low < high:
10         middle = (low + high) // 2
11         mergeSortHelper(lyst, copyBuffer, low, middle)
12         mergeSortHelper(lyst, copyBuffer, middle + 1, high)
13         merge(lyst, copyBuffer, low, middle, high)
14 
15 def merge(lyst, copyBuffer, low, middle, high):
16     i1 = low
17     i2 = middle + 1
18 
19     for i in range(low, high + 1):
20         if i1 > middle:
21             copyBuffer[i] = lyst[i2]  #first sublist exhaust
22             i2 += 1
23         elif i2 > high:
24             copyBuffer[i] = lyst[i1]  #second sublist exhaust
25             i1 += 1
26         elif lyst[i1] < lyst[i2]:
27             copyBuffer[i] = lyst[i1]  # item in first sublist
28             i1 += 1
29         elif lyst[i1] > lyst[i2]:
30             copyBuffer[i] = lyst[i2]     #item in second sublist
31             i2 += 1
32         else:
33             pass
34 
35     for i in range(low, high + 1):    #copy sorted items to lyst
36         lyst[i] = copyBuffer[i]
37 
38 def main(size=10, sort=mergeSort):
39     lyst = []
40     for count in range(size):
41         while len(lyst) < 8:
42             num = random.randint(1, size + 1)
43             if num not in lyst:
44                 lyst.append(num)
45     print(lyst)
46     mergeSort(lyst)
47     print(lyst)
48 
49 if __name__ == '__main__':
50     main()

根据列表的大小,合并排序有两个空间需求,首先是在支持递归调用的调用栈上需要O(log2^n),其次在复制缓存需要使用O(n)的空间

因此合并排序算法的复杂度为O(nlog2^n)

标签:排序,copyBuffer,列表,算法,swap,数据结构,lyst,def
From: https://www.cnblogs.com/huangm1314/p/10941139.html

相关文章

  • 路径规划算法 - 求解最短路径 - Dijkstra算法
    Dijkstra算法的思想是广度优先搜索(BFS)贪心策略。是从一个顶点到其余各顶点的最短路径算法,节点边是不各自不同的权重,但都必须是正数如果是负数,则需要Bellman-Ford算法如果想求任意两点之间的距离,就需要用Floyd算法求节点0->4的最短路径每次从未标记的节点中选择距离......
  • 拒绝算法推荐,使用rss订阅消息与新闻!
    算法推荐的弊端就不说了借用RSSHub镜像网站如果你实在不会,又或者觉得麻烦,那你还可以搭其他网友的“便车”。我收集了 9 个公开的 RSShub镜像网站,它们用的都是用自己的服务器,所以在流量方面也不会有问题。服务器1 :https://rsshub.rssforever.com 服务器2 :https://rss......
  • java与算法Day1 Scanner的应用(一)
    java中使用输入需要用到java.util.Scanner。Scanner有next,nextInt,nextString,hasNext,hasNextLine等方法。使用XXX variable=Scanner.NextXXX就可以获取一个输入值。next系列的方法,他们的作用都是从键盘中接收数据。当程序执行到他们的时候,在命令行中就开始等待键盘输入了,而......
  • 文心一言 VS 讯飞星火 VS chatgpt (130)-- 算法导论11.2 2题
    二、用go语言,对于一个用链接法解决冲突的散列表,说明将关键字5,28,19,15,20,33,12,17,10插入到该表中的过程。设该表中有9个槽位,并设其散列函数为h(k)=kmod9。文心一言:在这个问题中,我们使用Go语言来解决一个散列(Hash)表的问题,该问题需要我们使用链接法解决冲突。我们的散列......
  • 文心一言 VS 讯飞星火 VS chatgpt (129)-- 算法导论11.1 4题
    四、用go语言,我们希望在一个非常大的数组上,通过利用直接寻址的方式来实现一个字典。开始时该数组中可能包含一些无用信息,但要对整个数组进行初始化是不太实际的,因为该数组的规模太大。请给出在大数组上实现直接寻址字典的方案。每个存储对象占用O(1)空间;SEARCH、INSERT和DELETE操......
  • Xlinx FPGA for DSP CORDIC 算法
    https://wenku.baidu.com/view/6c623aa8910ef12d2bf9e732.html?_wkts_=1701401816748&needWelcomeRecommand=1           ......
  • 2023/12/5日 学习Java数据结构
    今日学习了单链表和一部分的双向链表,还有一个月的时间就要期末考试了,但是我的数据结构还是一点也不会,只能抓紧学了packagecom.ityuhao;importjavax.swing.*;publicclassLinkList{//头节点privateNodehead;//链表长度publicintlength;//创......
  • 单调栈与单调队列算法总结
    单调栈知识概览单调栈最常见的应用是找到每一个数离它最近的且比它小的数。单调栈考虑的方式和双指针类似,都是先想一下暴力做法是什么,然后再挖掘一些性质如单调性,最终可以把目光集中在比较少的状态中,从而达到降低时间复杂度的作用,都是算法优化的一种手段。对于的情况,更有可能......
  • 代码随想录算法训练营第六天| 454.四数相加 15.三数之和 18.四数之和
    LeetCode454.四数相加题目链接:LeetCode454思路: 将两个数组中的数存放到一个map中,用另外两个数组的值在map中去减 classSolution{public:intfourSumCount(vector<int>&A,vector<int>&B,vector<int>&C,vector<int>&D){unordered_map&l......
  • 扩展欧几里得算法
    扩展欧几里得算法裴蜀定理(Bézout'slemma)定义设\(a,b\)是不全为零的整数,对任意整数\(x,y\),满足\(\gcd(a,b)\midax+by\),且存在整数\(x,y\),使得\(ax+by=\gcd(a,b)\).证明对于第一点由于\(\gcd(a,b)\mida,\gcd(a,b)\midb\)所以\(\gcd(a,b)\midax,\gcd(a,b)\mid......