『案例』十大经典排序算法(含动图,Python实现)

排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。用一张图概括:

关于稳定性

名词解释

1、冒泡排序

冒泡排序(BubbleSort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

作为最简单的排序算法之一,冒泡排序给我的感觉就像Abandon在单词书里出现的感觉一样,每次都在第一页第一位,所以最熟悉。冒泡排序还有一种优化算法,就是立一个flag,当在一趟序列遍历中元素没有发生交换,则证明该序列已经有序。但这种改进对于提升性能来说并没有什么太大作用。

defbubbleSort(arr):foriinrange(1,len(arr)):forjinrange(0,len(arr)-i):ifarr[j]>arr[j+1]:arr[j],arr[j+1]=arr[j+1],arr[j]returnarr2、选择排序

defselectionSort(arr):foriinrange(len(arr)-1):#记录最小数的索引minIndex=iforjinrange(i+1,len(arr)):ifarr[j]

插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴,但它的原理应该是最容易理解的了,因为只要打过扑克牌的人都应该能够秒懂。插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

插入排序和冒泡排序一样,也有一种优化算法,叫做拆半插入。

definsertionSort(arr):foriinrange(len(arr)):preIndex=i-1current=arr[i]whilepreIndex>=0andarr[preIndex]>current:arr[preIndex+1]=arr[preIndex]preIndex-=1arr[preIndex+1]=currentreturnarr4、希尔排序

希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。

希尔排序是基于插入排序的以下两点性质而提出改进方法的:

希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。

defshellSort(arr):importmathgap=1while(gap0:foriinrange(gap,len(arr)):temp=arr[i]j=i-gapwhilej>=0andarr[j]>temp:arr[j+gap]=arr[j]j-=gaparr[j+gap]=tempgap=math.floor(gap/3)returnarr5、归并排序

归并排序(Mergesort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(DivideandConquer)的一个非常典型的应用。

作为一种典型的分而治之思想的算法应用,归并排序的实现由两种方法:

defmergeSort(arr):importmathif(len(arr)<2):returnarrmiddle=math.floor(len(arr)/2)left,right=arr[0:middle],arr[middle:]returnmerge(mergeSort(left),mergeSort(right))defmerge(left,right):result=[]whileleftandright:ifleft[0]<=right[0]:result.append(left.pop(0));else:result.append(right.pop(0));whileleft:result.append(left.pop(0));whileright:result.append(right.pop(0));returnresult6、快速排序

快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序n个项目要Ο(nlogn)次比较。在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见。事实上,快速排序通常明显比其他Ο(nlogn)算法更快,因为它的内部循环(innerloop)可以在大部分的架构上很有效率地被实现出来。

快速排序使用分治法(Divideandconquer)策略来把一个串行(list)分为两个子串行(sub-lists)。

快速排序又是一种分而治之思想在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。

①从数列中挑出一个元素,称为“基准”(pivot);

②重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;

③递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;

递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会退出,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。

defquickSort(arr,left=None,right=None):left=0ifnotisinstance(left,(int,float))elseleftright=len(arr)-1ifnotisinstance(right,(int,float))elserightifleft

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:

defbuildMaxHeap(arr):importmathforiinrange(math.floor(len(arr)/2),-1,-1):heapify(arr,i)defheapify(arr,i):left=2*i+1right=2*i+2largest=iifleftarr[largest]:largest=leftifrightarr[largest]:largest=rightiflargest!=i:swap(arr,i,largest)heapify(arr,largest)defswap(arr,i,j):arr[i],arr[j]=arr[j],arr[i]defheapSort(arr):globalarrLenarrLen=len(arr)buildMaxHeap(arr)foriinrange(len(arr)-1,0,-1):swap(arr,0,i)arrLen-=1heapify(arr,0)returnarr8、计数排序

defcountingSort(arr,maxValue):bucketLen=maxValue+1bucket=[0]*bucketLensortedIndex=0arrLen=len(arr)foriinrange(arrLen):ifnotbucket[arr[i]]:bucket[arr[i]]=0bucket[arr[i]]+=1forjinrange(bucketLen):whilebucket[j]>0:arr[sortedIndex]=jsortedIndex+=1bucket[j]-=1returnarr9、桶排序

桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。为了使桶排序更加高效,我们需要做到这两点:

同时,对于桶中元素的排序,选择何种比较排序算法对于性能的影响至关重要。

当输入的数据可以均匀的分配到每一个桶中。

当输入的数据被分配到了同一个桶中。

defbucket_sort(s):桶排序min_num=min(s)max_num=max(s)#桶的大小bucket_range=(max_num-min_num)/len(s)#桶数组count_list=[[]foriinrange(len(s)+1)]#向桶数组填数foriins:count_list[int((i-min_num)//bucket_range)].append(i)s.clear()#回填,这里桶内部排序直接调用了sortedforiincount_list:forjinsorted(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、基数排序

基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。

基数排序有两种方法:

这三种排序算法都利用了桶的概念,但对桶的使用方法上有明显差异:

THE END
1.初阶数据结构常见五大排序算法及部分算法优化讨论2.内部排序:数据元素全部放在内存中的排序。 3.外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不断地在内外存之间移动数据的排序。 1.2常见的排序算法 代码语言:javascript 复制 // 排序实现的接口// 插入排序voidInsertSort(int*a,int n);// 希尔排序voidShellSort(int*a,int n);// 选择排序https://cloud.tencent.com.cn/developer/article/2476881
2.C语言归并排序(合并排序)算法以及代码合并排序算法c语言代码合并排序是采用分治法,先将无序序列划分为有序子序列,再将有序子序列合并成一个有序序列的有效的排序算法。 原理:先将无序序列利用二分法划分为子序列,直至每个子序列只有一个元素(单元素序列必有序),然后再对有序子序列逐步(两两)进行合并排序。合并方法是循环的将两个有序子序列当前的首元素进行比较,较小的https://blog.csdn.net/sinat_41942180/article/details/135094231
3.C语言合并排序及实例代码详解归并排序也称合并排序,其算法思想是将待排序序列分为两部分,依次对分得的两个部分再次使用归并排序,之后再对其进行合并。本文是小编搜索整理的关于C语言合并排序及实例代码详解,供参考学习,希望对大家有所帮助! 仅从算法思想上了解归并排序会觉得很抽象,接下来就以对序列A[0], A[l]…, A[n-1]进行升序排列来进https://www.oh100.com/kaoshi/c/468042.html
4.Java经典排序算法之归并排序实现代码java这篇文章主要介绍了Java经典排序算法之归并排序实现代码,归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用,将已有序的子序列合并,得到完全有序的序列,需要的朋友可以参考下 + 目录 1.简介 归并排序(MERGESORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(https://www.jb51.net/program/302236u1e.htm
5.算法入门用Python手写五大经典排序算法,看完这篇终于懂了就像冒泡排序一样,插入排序算法的实现也很简单。尽管插入排序是O(n 2)算法,但在实践中它也比其他二次实现(例如冒泡排序)更有效。 有更强大的算法,包括合并排序和快速排序,但是这些实现是递归的,在处理小型列表时通常无法击败插入排序。如果列表足够小,可以提供更快的整体实现,则某些快速排序实现甚至在内部使用插入排https://cloud.tencent.com/developer/article/1632862
6.归并排序算法及其实现代码详解天之道归并排序算法及其实现代码详解 归并排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。 例如,有数列{6,202,100,301,38,8,1} 1. 刚开始的分组如下:http://www.cppblog.com/zhenglinbo/archive/2012/11/25/195666.html
7.C语言顺序表,合并并排序(代码注释讲解)51CTO博客C语言顺序表,合并并排序(代码注释讲解),/*.已知有两个按元素值递增有序的顺序表A和B,设计一个算法将表A和表B的全部元素归并为一个按元素值非递减有序的顺序表C。https://blog.51cto.com/u_15677788/5369253
8.常见算法4合并(归并)排序Mergesort二、算法原理: 假如如我这里有一组数据,归并排序过程如下: 通俗点来说,就是先分割,再合并。分割的过程中其实可理解为就是以二分法将数组分割成最小单元,然后再按顺序合并起来。 动图演示 三、代码实现: 1、Python 3 : #分割defmerge_sort(arr):importmathiflen(arr)<2:returnarrelse:middle=math.floor(lenhttps://www.jianshu.com/p/b1383cf28b6b
9.排序算法总结菜鸟教程冒泡排序 平均时间复杂度:O(n2) java代码实现: 实例 public static void BubbleSort(int [] arr){ int temp;//临时变量 for(int i=0; i<arr.length-1; i++){ //表示趟数,一共arr.length-1次。 for(int j=arr.length-1; j>i; j--){ if(arr[j] < arr[j-1]){ temp = arr[j]; arhttps://www.runoob.com/w3cnote/sort-algorithm-summary.html
10.121.合并两个已排序的数组(MergeSortedArray)如果数组2 后循环完,那么再来一个while把剩余的给弄到结果里。 代码: class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { int tail1 = m - 1; int tail2 = n - 1; int finished = m + n - 1; https://zhuanlan.zhihu.com/p/373167164
11.JavaLambdaQueryWrapper连表查询java对链表的数据进行排序在最后一篇博客中,它解释了九种内部排序算法,一些算法也提供了代码实现,但这些代码实现是基于数组排序的。本博客通过链表排序为读者实现了几种常见的排序算法。 实现链表的快速排序 算法思想:对于链表,以head节点的值作为key,然后通过节点,可以得到小于key的链表和大于等于key的链表;因此,递归可以分别快速执行两个链表。https://www.tulingxueyuan.cn/tlzx/jsp/2564.html
12.merge(归并排序算法)merge是建立在归并操作上的一种有效的排序算法。它将多个排序列表作为输入并生成单个列表作为输出,包含按排序顺序排列的输入列表的所有元素。简介 归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使https://baike.baidu.com/item/merge/13680638
13.(完整版)数据结构算法大全有代码20211107005254.pdf(完整版)数据结构算法大全有代码.pdf,排序算法有:插入排序,合并排序,冒泡排序,选择排序,希尔排序,堆排序,快速排序, 计数排序,基数排序,桶排序(没有实现)。比较一下学习后的心得。 我不是很清楚他们的时间复杂度,也真的不知道他们到底谁快谁慢,因为书上的推导https://max.book118.com/html/2021/1107/6141221235004042.shtm