太牛了!用Python实现十大经典排序算法!转载
原创大家好,我是菜鸟兄弟!大家好,我是菜鸟兄弟!大家好,我是菜鸟兄弟!大家好,我是菜鸟兄弟!
排序算法是数据结构和算法中最基本的算法之一。
排序算法可以分为内部排序和外部排序。内部排序是在内存中对数据记录进行排序,而外部排序是排序过程需要访问外部存储器,因为排序的数据太大,无法同时容纳所有排序的记录。常用的内部排序算法有:插入排序,Hill排序,Hill排序,选择排序,按选择排序,选择排序,冒泡排序,冒泡排序,冒泡排序、包含排序、快速排序、快速排序、堆排序、基排序等。
关于时间复杂性关于时间复杂性关于时间复杂性
-
平方阶 (O(n2)) 排序 各种类型的简单排序:直接插入、直接选择和冒泡排序。
-
线性对数阶 (O(nlog2n)) 排序 快速排序、堆排序和包含排序。
-
O(n1+§)) 排序,§ 是介于 0 和 1 Hill排序之间的常量
-
线性阶 (O(n)) 排序 基本分类,除了桶和箱分类。
关于稳定性关于稳定性关于稳定性
-
排序后 2 等值键的顺序与排序前的顺序相同
-
稳定的排序算法:冒泡排序,插入排序,插入排序、包含排序和基排序。
-
排序算法不稳定:选择排序、快速排序、快速排序、Hill排序、堆排序。
名词解释
-
n:数据大小数据大小
-
k桶数桶数桶数
-
In-place:内存使用量恒定,不会增加内存使用量
-
Out-place:占用额外内存:占用额外内存:额外内存使用量:额外内存消耗
1,冒泡排序,冒泡排序,冒泡排序
冒泡排序(冒泡排序(冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它反复遍历要排序的序列,一次比较两个元素,如果它们的顺序错误,则交换它们。重复遍历该系列,直到不再需要掉期,这意味着该系列已被排序。该算法得名于这样一个事实,即通过交换将较小的元素缓慢地“浮动”到序列的顶部。
作为最简单的排序算法之一,冒泡排序给我的感觉是 Abandon 在字书上出现的感觉是一样的,每次都在第一页第一页,所以最熟悉。气泡排序还有另一种优化算法,那就是设置一个 flag如果在序列遍历期间没有发生元素交换,则序列被证明是有序的。然而,这种改进并不能很好地提高性能。
(1算法步骤)算法步骤
-
比较相邻元素。如果第一个比第二个大,则两个都互换。
-
对每一对相邻元素执行相同的操作,从开始的第一对元素到末尾的最后一对元素。完成这一步后,最后一个元素将是最大的数字。
-
对除最后一个元素以外的所有元素重复上述步骤。
-
一次对越来越少的元素重复上述步骤,直到没有更多的数字对可供比较。
(2电影演示)电影演示)电影演示
(3)Python 代码
def bubbleSort(arr):
for i in range(1, len(arr)):
for j in range(0, len(arr)-i):
if arr[j] > arr[j+1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return arr
2,选择排序,按选择排序,选择排序
选择排序是一种简单直观的排序算法,无论放入什么数据都是 O(n²) 时间复杂性。因此,当您使用它时,数据大小越小越好。唯一的好处可能是它不会占用额外的内存空间。
(1算法步骤)算法步骤
-
首先在未排序的序列中找到最小(大)的元素,并将其存储在已排序序列的开头
-
然后继续从剩余的未排序元素中找到最小(大)的元素,并将其放在已排序序列的末尾。
-
重复第二步,直到所有元素都排序完毕。重复步骤2,直到所有元素都已排序。
(2电影演示)电影演示)电影演示
(3)Python 代码
def selectionSort(arr):
for i in range(len(arr) - 1):
# 记录最小数字的索引记录最小数字的索引
minIndex = i
for j in range(i + 1, len(arr)):
if arr[j] < arr[minIndex]:
minIndex = j
# i 如果不是最小数,则设置 i 最小交换数和最小交换数与最小数互换
if i != minIndex:
arr[i], arr[minIndex] = arr[minIndex], arr[i]
return arr
3,插入排序,插入排序
插入排序的代码实现不像冒泡排序和选择排序那样简单和粗暴,但其原理应该是最容易理解的,因为任何玩过扑克的人都应该能够在几秒钟内理解它。插入排序是最简单、最直观的排序算法之一。它的工作原理是构造一个有序的序列,对于未排序的数据,在排序的序列中向前和向后扫描以找到相应的位置并插入它。
插入排序和冒泡排序一样,也有一种称为对半插入的优化算法。
(1算法步骤)算法步骤
-
将第一个序列中要排序的第一个元素视为有序序列,将倒数第二个元素视为未排序序列。
-
从头到尾顺序地扫描未排序的序列,并将扫描的每个元素插入到有序序列中的适当位置。(如果要插入的元素等于有序序列中的元素,则要插入的元素被插入在相等的元素之后。)
(2电影演示)电影演示)电影演示
(3)Python 代码
def insertionSort(arr):
for i in range(len(arr)):
preIndex = i-1
current = arr[i]
while preIndex >= 0 and arr[preIndex] > current:
arr[preIndex+1] = arr[preIndex]
preIndex-=1
arr[preIndex+1] = current
return arr
4,Hill排序,Hill排序
Hill排序,也被称为递减增量排序算法,是插入排序的一个更高效和改进的版本。然而,Hill排序是一种非稳定的排序算法。
Hill排序是一种基于插入排序的以下两个属性的改进方法。
-
(A)当对几乎已经有序的数据进行操作时,插入排序是有效的,即,它可以实现线性排序的效率。
-
但插入排序通常效率较低,因为它们一次只能将数据移动到一个位置。
Hill排序的基本思想是将待排序的整个记录序列分成几个子序列进行直接插入排序,当整个序列中的记录基本有序时,再对整个序列进行直接插入排序。
(1算法步骤)算法步骤
-
选择递增序列选择递增序列选择递增序列 t1,t2,……,tk,其中 ti > tj, tk = 1;
-
按增量序列数按增量序列数按增量序列号 k到序列以执行序列到序列 k 趟排序;
-
每次行程,根据相应的增量进行排序 ti要调度的序列被分成多个长度的序列 m 子序列的直接插入排序,并且分别对每个子表执行直接插入排序。仅有的增量系数 1 当将整个序列视为表时,表的长度就是整个序列的长度。
(2)Python 代码
def shellSort(arr):
import math
gap=1
while(gap < len(arr)/3):
gap = gap*3+1
while gap > 0:
for i in range(gap,len(arr)):
temp = arr[i]
j = i-gap
while j >=0 and arr[j] > temp:
arr[j+gap]=arr[j]
j-=gap
arr[j+gap] = temp
gap = math.floor(gap/3)
return arr
5,合并排序,合并排序,合并和排序,合并排序
包含排序(包含排序)(子排序(子排序(Merge sort)是一种建立在包含运算基础上的高效排序算法。该算法基于分区方法(Divide and Conquer)用于非常典型的应用程序。)是一个非常典型的应用。)一个非常典型的应用程序。)这是一个非常典型的应用。
作为分而治之思想的典型算法应用,包含排序通过两种方法实现。
-
自上而下的递归(所有递归方法都可以使用迭代重写,因此有第一个 2 (一种方法)。(一种方法)。(一种方法)。
-
自下而上的迭代。自下而上迭代。自下而上迭代。
与选择排序类似,包含排序的性能不受输入数据的影响,但它的性能比选择排序要好得多,因为它始终 O(nlogn) 成本的时间复杂性是所需的额外存储空间。
(1算法步骤)算法步骤
-
请求空间,以便其大小是两个已排序序列的总和,并且该空间用于存储合并的序列。
-
设置两个指针,最初位于两个已排序序列的起始处。
-
比较两个指针所指向的元素,选择要放入合并空间的相对较小的元素,然后将指针移动到下一个位置。
-
重复步骤 3 直到指针到达序列的末尾。
-
将另一个序列的所有剩余元素直接复制到合并序列的末尾。
(2电影演示)电影演示)电影演示
(3)Python 代码
def mergeSort(arr):
import math
if(len(arr)<2):
return arr
middle = math.floor(len(arr)/2)
left, right = arr[0:middle], arr[middle:]
return merge(mergeSort(left), mergeSort(right))
def merge(left,right):
result = []
while left and right:
if left[0] <= right[0]:
result.append(left.pop(0));
else:
result.append(right.pop(0));
while left:
result.append(left.pop(0));
while right:
result.append(right.pop(0));
return result
6、快速排序、快速排序
快速排序由托尼组成快速排序由托尼组成快速排序由托尼组成·霍尔开发的一种排序算法。在平均条件下,排序 n 个项目要 Ο(nlogn) 第二个比较。在最坏的情况下,有必要 Ο(n2) 次比较,但这种情况并不常见。事实上,快速排序通常比其他排序好得多 Ο(nlogn) 算法更快是因为它的内部循环(算法更快是因为它的内部循环(inner loop)可以在大多数体系结构上非常有效地实施。
使用分区方法的快速排序(快速排序使用分区方法(快速排序使用分区(快速排序使用分区方法(Divide and conquer)策略来放置序列()策略来放置序列()策略来组合序列()策略来放置序列()策略list)分为两个子串行()分为两个子串行(sub-lists)。
快速排序是分而治之思想在排序算法中的另一个典型应用。从本质上讲,快速排序应该被看作是一种基于冒泡排序的递归分治方法。
Quick Sort这个名字简单而残酷,因为你一听到这个名字就知道它的存在是为了什么,那就是快速高效!这是目前处理大数据最快的排序算法之一。虽然 Worst Case 的时间复杂度为的时间复杂度为 O(n²)但它们是优秀的,在大多数情况下都好于 O(n logn) 排序算法执行得更好,但为什么会这样,我不知道。嗯,我的强迫症再次战胜了我,抬头看了看 N 多个来源最终在算法艺术和信息学竞赛中找到了满意的答案
快速排序的最坏情况运行是快速排序的最坏情况操作 O(n²)例如,一列快速的顺序序列。但它的均衡预期时间是 O(nlogn),且 O(nlogn) 符号中隐含的常量因子很小,并且特定的复杂性稳定地等于 O(nlogn) 包含类的数量要小得多。因此,对于大多数弱阶随机数列,快速排序总是好于包含排序。
(1算法步骤)算法步骤
① 从序列中选取元素称为从序列中选取元素,称为从序列中选取元素称为从序列中选取元素 “基准”(“基准”)(“基准”(pivot);
② 重新排序系列,将所有小于基准值的元素放在基准之前,将所有大于基准值的元素放在基准后面(相同的数字可以放在两边)。退出此分区后,基准位于系列的中间。这称为分区(partition)操作;
③ 递归地(recursive)对小于基值的元素子系列和大于基值的元素子系列进行排序。
递归的最基本情况是数组的大小是零或一,这意味着它总是已经排序的。尽管算法继续递归运行,但它总是退出,因为在每次迭代(iteration),它将至少将一个元素放置到其最后位置。
(2电影演示)电影演示)电影演示
(3)Python 代码
def quickSort(arr, left=None, right=None):
left = 0 if not isinstance(left,(int, float)) else left
right = len(arr)-1 if not isinstance(right,(int, float)) else right
if left < right:
partitionIndex = partition(arr, left, right)
quickSort(arr, left, partitionIndex-1)
quickSort(arr, partitionIndex+1, right)
return arr
def partition(arr, left, right):
pivot = left
index = pivot+1
i = index
while i <= right:
if arr[i] < arr[pivot]:
swap(arr, i, index)
index+=1
i+=1
swap(arr,pivot,index-1)
return index-1
def swap(arr, i, j):
arr[i], arr[j] = arr[j], arr[i]
7、堆排序
堆排序(Heapsort)是指使用类似堆的数据结构设计的排序算法。堆是一种结构,它近似于一棵完整的二叉树,并且满足堆的两个属性:即,子节点的键或索引始终小于(或大于)其父节点。堆排序可以被描述为使用堆的概念进行排序的选择排序。有两种方法。
-
大顶堆:每个节点的值都大于或等于其子节点的值,并用于堆排序算法中的升序。
-
(A)小顶堆:每个节点的值小于或等于其子节点的值,并按降序在堆排序算法中使用。
堆排序的平均时间复杂度是堆排序的平均时间复杂度是 Ο(nlogn)。
(1算法步骤)算法步骤
-
创建堆创建堆 H[0……n-1];
-
调换堆的顶部(最大值)和底部。
-
减小堆的大小 1,并调用 shift_down(0)其目的是将新数组顶部的数据调整到相应位置。
-
重复步骤 2直到堆的大小达到该堆大小 1。
(2电影演示)电影演示)电影演示
(3)Python 代码
def buildMaxHeap(arr):
import math
for i in range(math.floor(len(arr)/2),-1,-1):
heapify(arr,i)
def heapify(arr, i):
left = 2*i+1
right = 2*i+2
largest = i
if left < arrLen and arr[left] > arr[largest]:
largest = left
if right < arrLen and arr[right] > arr[largest]:
largest = right
if largest != i:
swap(arr, i, largest)
heapify(arr, largest)
def swap(arr, i, j):
arr[i], arr[j] = arr[j], arr[i]
def heapSort(arr):
global arrLen
arrLen = len(arr)
buildMaxHeap(arr)
for i in range(len(arr)-1,0,-1):
swap(arr,0,i)
arrLen -=1
heapify(arr, 0)
return arr
8,计数排序,计数排序,计数排序
计数排序的核心在于将输入的数据值转换为键,以存储在额外的开放数组空间中。作为一种线性时间复杂度排序,计数排序要求输入数据必须是具有一定范围的整数。
(1电影演示)电影演示)电影演示
(2)Python 代码
def countingSort(arr, maxValue):
bucketLen = maxValue+1
bucket = [0]*bucketLen
sortedIndex =0
arrLen = len(arr)
for i in range(arrLen):
if not bucket[arr[i]]:
bucket[arr[i]]=0
bucket[arr[i]]+=1
for j in range(bucketLen):
while bucket[j]>0:
arr[sortedIndex] = j
sortedIndex+=1
bucket[j]-=1
return arr
9、桶排序
桶排序是计数排序的升级版本。它利用了函数之间的映射关系,而效率的关键在于该映射函数的确定。为了提高存储桶排序的效率,我们需要做以下两件事。
-
当有额外空间时,最大限度地增加桶的数量
-
使用的映射函数能够接受输入 N 数据均匀分布在数据之间均匀分布 K 个桶中
同时,对于存储桶中的元素进行排序,比较排序算法的选择对性能的影响至关重要。
什么时候最快?最快的是什么时候?
当输入数据可以均匀地分配到每个存储桶时。
什么时候最慢?
当输入数据被分配到相同的存储桶时。
Python 代码
def bucket_sort(s):
"""桶排序"""
min_num = min(s)
max_num = max(s)
# 桶的大小
bucket_range = (max_num-min_num) / len(s)
# 桶数组
count_list = [ [] for i in range(len(s) + 1)]
# 用数字填充存储桶数组,用填充存储桶数组的数字填充存储桶数组
for i in s:
count_list[int((i-min_num)//bucket_range)].append(i)
s.clear()
# 回填,其中存储桶的内部排序直接调用sorted
for i in count_list:
for j in sorted(i):
s.append(j)
if __name__ == __main__ :
a = [3.2,6,8,4,2,6,7,3]
bucket_sort(a)
print(a) # [2, 3, 3.2, 4, 6, 6, 7, 8]
10,基本排序,基本排序
基本排序是一种非比较整数排序算法,其工作原理是将整数按数字分割成不同的数字,然后按每个数字分别进行比较。由于整数还可以以特定格式表示字符串(如名称或日期)和浮点数,基数排序不仅适用于整数。
基数排序 vs 计数排序 vs 桶排序
基数排序有两种方法。基数排序有两种方法。有两种基本排序方法。
这三种排序算法都利用了桶的概念,但它们的使用方式有很大的不同。
-
基本排序:根据键值的每个数字分配存储桶。
-
计数排序:每个存储桶只存储一个键值。
-
存储桶排序:每个存储桶存储一定范围的值。
动图演示
Python 代码
def RadixSort(list):
i = 0 #最初按数字排序最初按数字排序最初按单个数字排序最初按单个数字排序
n = 1 #将最小位数设置为最小位数1(包含0)
max_num = max(list) #获取排序数组中的最大值
while max_num > 10**n: #获取最大位数获取最大位数获取最大位数
n += 1
while i < n:
bucket = {} #使用词典构建存储桶使用词典构建存储桶使用词典构建存储桶
for x in range(10):
bucket.setdefault(x, []) #清空每桶清空每桶清空
for x in list: #排序每一位排序每一位排序每一位置排序每一位置
radix =int((x / (10**i)) % 10) #获取每个人的基数获取每个基数的基数获取每个基数
bucket[radix].append(x) #将相应的数组元素添加到阶段 #在应定位底座的吊桶中
j = 0
for k in range(10):
if len(bucket[k]) != 0: #如果桶不为空,则桶不为空如果桶不为空,则桶不为空
for y in bucket[k]: #对于该存储桶中的每个元素、该存储桶中的每个元素、该存储桶中的每个元素
list[j] = y #放回数组放回数组
j += 1
i += 1
return list
赠书福利
▊《Python算法的奇妙之旅算法的奇妙之旅
[内容介绍[内容介绍]。[内容描述]。
-
Python语言,从基本算法开始并深入6每一个算法思想都伴随着大量生动有趣的案例,让读者从中学习Python同时认识到语法和算法的重要性,进而对算法产生了浓厚的兴趣。
-
结合40多个典型案例及其对应的几个典型案例及其对应100多种解题思路和方法,介绍了遍历、迭代、递归、回溯、贪婪方法和划分方法6各种算法思想,涵盖算法的基本思想、关键特征、求解步骤和框架。
感谢暖女士为我们提供了这本书
赠书规则
赠书规则:会把书送到小帮手的朋友圈里,公众后台输入:小帮手,找他去拿吧!
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除