常见的几种排序算法
一:冒泡排序
基本思想:从头开始比较两个数大小,较大的数下沉,较小的数冒起来,如果第二个数小,就交换位置,这样每循环一次最大的数都会跑到最后
最坏时间复杂度:O(n2)
最优时间复杂度:O(n) 表示遍历一次发现没有可以交换的元素,即无需排序
稳定性:稳定
代码实现:
def bubble_sort(arr): for i in range(len(arr) - 1): count = 0 for j in range(len(arr) - 1 - i): if arr[j] > arr[j + 1]: arr[j + 1], arr[j] = arr[j], arr[j + 1] count += 1 # 对算法的优化,当某次循环后,列表结构并没发生变化,说明列表已排序完成,无需进行后续的循环冒泡操作 if count == 0: return arr return arr
二:选择排序
基本思想:将数组理解为两部分即已排序部分和未排序部分,每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。
最坏时间复杂度:O(n2)
最优时间复杂度:O(n2)
稳定性:不稳定
代码实现:
def select_sort(arr): for i in range(len(arr) - 1): min = i for j in range(i+1, len(arr)): if arr[min] > arr[j]: min = j
# 遍历所有未排序元素,将其中最小的数据和已排序部分的最后一个元素进行交换 arr[i], arr[min] = arr[min], arr[i] return arr
三:插入排序
基本思想:将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序
最坏时间复杂度:O(n2)
最优时间复杂度:O(n)
稳定性:稳定
代码实现:
def insert_sort(arr): # 从列表的第二个位置开始向前插入 for i in range(1,len(arr)): for j in range(i,0,-1): # 从第i个元素开始向前进行比较,如果小于前面那个数就交换位置 if arr[j]<arr[j-1]: arr[j],arr[j-1]=arr[j-1],arr[j] # 对算法的优化 一旦后一个元素比前一个元素大 那么后续的比较就没有意义了 else: break return arr
四:希尔排序
基本思想:希尔排序是把列表按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的元素越来越多,当增量减至1时,整个列表恰被分成一组,算法便终止
最坏时间复杂度:O(n2)
最优时间复杂度:O(n1.3)
稳定性:不稳定
代码实现:
def shell_sort(arr): # 规定增量 gap=len(arr)//2 while gap>0: for i in range(gap,len(arr)): # 按增量分好的的组进行插入排序,同组中每个元素的index值相差gap while i-gap>=0: if arr[i]<arr[i-gap]: arr[i],arr[i-gap]=arr[i-gap],arr[i] i=i-gap else: break # 增量减半 gap=gap//2 return arr
五:快速排序
基本思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
最坏时间复杂度:O(n2)
最优时间复杂度:O(nlogn)
稳定性:不稳定
代码实现:
def quick_sort(arr, first, last): """ 使用递归进行快速排序 :param arr: 要进行排序的列表 :param first: 列表的起始点(例 快排初始列表传入的起始点为 0 终止点为len(arr)-1 ) :param last: 列表的终止点 """ # 递归的结束条件 if first >= last: return # 选取笔杆值 比笔杆值大的都放在笔杆值右边 比笔杆值小的都放在笔杆值左边 mid_value = arr[first] low = first high = last while low < high: while low < high and arr[high] >= mid_value: high -= 1 arr[low] = arr[high] while low < high and arr[low] < mid_value: low += 1 arr[high] = arr[low] arr[low] = mid_value # 递归调用 以笔杆值为分隔传入要排序的某段列表 quick_sort(arr, first, low - 1) quick_sort(arr, low + 1, last)
六:归并排序
基本思想:将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序
最坏时间复杂度:O(nlogn)
最优时间复杂度:O(nlogn)
稳定性:稳定
特点:时间复杂度低,但是最终返回的是一个新的列表,需要开辟新的内存空间去保存,而上述其他排序算法都是在原列表上进行操作,并不涉及到空间上的改变
代码实现:
def merge_sort(arr): n = len(arr) # 拆分列表的递归终止条件(把原列表拆成只有单个元素的列表) if n <= 1: return arr mid = n // 2 # 归并排序后形成的有序的新列表 left_arr = merge_sort(arr[:mid]) # 归并排序后形成的有序的新列表 right_arr = merge_sort(arr[mid:]) left_pointer, right_pointer = 0, 0 # 两个有序列表合并成一个有序的列表 result = [] while left_pointer < len(left_arr) and right_pointer < len(right_arr): if left_arr[left_pointer] <= right_arr[right_pointer]: result.append(left_arr[left_pointer]) left_pointer += 1 else: result.append(right_arr[right_pointer]) right_pointer += 1 result += left_arr[left_pointer:] result += right_arr[right_pointer:] return result
浙公网安备 33010602011771号