电子说
在计算机科学领域中,排序算法是一种基本的算法。排序算法可以将一个数据集合重新排列成一个按照某种规则有序的集合,常用于数据检索、数据压缩、数据加密等场合。在实际的应用中,我们需要根据不同的场景选择不同的排序算法,以达到最优化的效果。
本文将详细介绍8种最常用的排序算法,包括插入排序、冒泡排序、选择排序、快速排序、归并排序、希尔排序、堆排序和计数排序。我们将从算法原理、改进方案,再到代码兑现的角度透彻解析这8种排序算法,以帮助读者更好地理解和应用这些算法。
插入排序是最简单的排序算法之一,它的基本思想是将一个记录插入到已排好序的有序表中,从而得到一个新的、记录数增1的有序表。具体实现时,我们从第2个元素开始依次将每个元素与前面的有序序列比较,然后找到它的正确位置插入即可。插入排序的时间复杂度为O(n^2),但是在小规模数据的排序中效率较高。
插入排序的改进方案有希尔排序,它是插入排序的一种改进版,基本思想是将待排序的数组分割成若干个小的子数组,对这些子数组进行插入排序,然后再对整个数组进行一次插入排序。希尔排序的时间复杂度为O(nlogn)。
以下是插入排序的代码实现:
definsert_sort(array): n =len(array)fori inrange(1, n): key =array[i] j = i -1whilej >=0andarray[j] > key: array[j +1] = array[j] j -=1array[j +1] = keyreturnarray
冒泡排序是一种简单的排序算法,它的基本思想是重复地遍历要排序的数组,每次比较相邻的两个元素,如果它们的顺序错误就交换它们的位置。冒泡排序的时间复杂度为O(n^2),但是它的空间复杂度比插入排序低,因为它只需要一个额外的空间来存储交换时的中间值。
冒泡排序的改进方案有鸡尾酒排序,它是冒泡排序的一种改进版,它的基本思想是先从左到右遍历数组,然后从右到左遍历数组,再从左到右遍历数组,以此类推。鸡尾酒排序的时间复杂度与冒泡排序相同,但是在某些情况下它的效率更高。
以下是冒泡排序的代码实现:
def bubble_sort(array): n = len(array)foriinrange(n -1):forjinrange(n - i -1):ifarray[j] >array[j +1]:array[j],array[j +1] =array[j +1],array[j]returnarray
选择排序是一种简单直观的排序算法,它的基本思想是每次选择一个最小的元素,并将它放在序列的起始位置。选择排序的时间复杂度为O(n^2),但是由于它每次只需要交换一次,因此它的运行时间与数据的初始状态无关。
以下是选择排序的代码实现:
defselection_sort(array): n =len(array)fori inrange(n -1): min_index =iforj inrange(i +1, n): if array[j] < array[min_index]: min_index =j array[i], array[min_index] = array[min_index], array[i]returnarray
快速排序是一种分治思想的排序算法,它的基本思想是通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可以分别对这两部分记录继续进行排序,以达到整个序列有序的目的。快速排序的时间复杂度为O(nlogn),但是在最坏情况下时间复杂度为O(n^2)。
以下是快速排序的代码实现:
def quick_sort(array):iflen(array) <2:returnarraypivot =array[0] less = [xforx inarray[1:]ifx <= pivot] greater = [xforx inarray[1:]ifx > pivot]returnquick_sort(less) + [pivot] + quick_sort(greater)
归并排序是一种分治思想的排序算法,它的基本思想是将待排序的序列分成若干个子序列,每个子序列都是有序的,然后再将子序列合并成整体有序序列。归并排序的时间复杂度为O(nlogn)。
以下是归并排序的代码实现:
def merge_sort(array): if len(array)<2:returnarraymid=len(array)//2left=merge_sort(array[:mid])right=merge_sort(array[mid:])result=[] i=j=0while i<len(left)andj
堆排序是一种树形选择排序,它的基本思想是将待排序序列构造成一个堆,然后依次将堆顶元素和末尾元素交换,然后重新调整堆。堆排序的时间复杂度为O(nlogn)。
以下是堆排序的代码实现:
def heapify(array, n, i): largest=ileft=2*i+1right=2*i+2ifleft<nandarray[left]>array[largest]: largest=leftifright<nandarray[right]>array[largest]: largest=rightif largest!=i:array[i],array[largest]=array[largest],array[i] heapify(array, n, largest) def heap_sort(array): n=len(array)foriinrange(n//2-1,-1,-1): heapify(array, n, i)foriinrange(n-1,0,-1):array[0],array[i]=array[i],array[0] heapify(array, i,0)returnarray七、希尔排序
希尔排序是一种改进版的插入排序,它的基本思想是将待排序序列按照一定间隔分成若干个子序列,然后对子序列进行插入排序,最后再对整个序列进行插入排序。希尔排序的时间复杂度与间隔序列的选取有关,最优的时间复杂度为O(nlogn)。
以下是希尔排序的代码实现:
defshell_sort(array): n =len(array) gap = n// 2whilegap >0:fori inrange(gap, n): temp = array[i] j = iwhilej >= gapandarray[j - gap] > temp: array[j] = array[j - gap] j -= gap array[j] = temp gap//= 2returnarray
八、计数排序
计数排序是一种非比较排序,它的基本思想是统计待排序序列中每个元素出现的次数,然后依次将每个元素输出,计数排序的时间复杂度为O(n+k),其中k为最大值和最小值之差。
以下是计数排序的代码实现:
def counting_sort(array): max_value=max(array) min_value=min(array) count=[0]*(max_value-min_value+1)fornuminarray: count[num-min_value]+=1res=[]foriinrange(len(count)): res+=[i+min_value]*count[i]returnres