排序算法稳定性

八大排序算法的 Python 实现

孤街浪徒 提交于 2019-11-29 15:19:56
转载: 八大排序算法的 Python 实现 本文用Python实现了插入排序、希尔排序、冒泡排序、快速排序、直接选择排序、堆排序、归并排序、基数排序。 1、插入排序 描述 插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就只包含这一个元素(即待插入元素)。在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中。 代码实现 def insert_sort(lists): # 插入排序 count = len(lists) for i in range(1, count): key = lists[i] j = i - 1 while j >= 0: if lists[j] > key: lists[j + 1] = lists[j] lists[j] = key j -= 1 return lists 2、希尔排序 描述 希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因DL.Shell于1959年提出而得名。

python实现各种排序算法

邮差的信 提交于 2019-11-29 15:18:06
冒泡排序 """ 分析 1. 算法是一种与语言无关的东西,更确切地说就算解决问题的思路,就是一个通用的思想的问题 2. 冒泡算法作为最简单的一种排序算法,我们的关注点不应该是代码本身,而应该是思想 3. 冒泡排序思想的侧重点有两点:走一趟干到底选出最大的放到右边;走几趟能够把整个序列都排序完毕 4. 当走一趟干到底的时候考虑的是j的取值, 而不是j+1, 这样能清晰地知道range的范围应该是什么 5. is_ordered 标志位:如果有序列表就不再排序,直接退出 6. 两个for循环的考虑顺序:先考虑内层循环的意义,再考虑外层循环的意义 """ def bubble_sort(alist): n = len(alist) # i 代表的是第几趟,从1开始,表示第一趟 for i in range(1, n): is_ordered = True # j 表示走一趟 for j in range(n-i): if alist[j] > alist[j+1]: alist[j], alist[j+1] = alist[j+1], alist[j] is_ordered = False if is_ordered: return if __name__ == '__main__': lis = [9, 11, 2, 2, 1, 20, 13] bubble_sort(lis)

排序算法(4):希尔排序

爷,独闯天下 提交于 2019-11-29 10:23:22
基本思想 h有序数组 一个数组中任意间隔为 h h h 的元素都是有序的,那这个数组就是 h有序数组 。如下图所示这个数组就是一个 h h h 有序数组,其中 h = 4 h=4 h = 4 。可以看到,虽然整个数组是乱序的,但任意相隔 h = 4 h=4 h = 4 的元素都是有序的。 希尔排序 希尔排序的思想就是,首先让数组 h h h 有序,然后不断减小 h h h 的值。试想一下,当 h = 1 h=1 h = 1 的时候,数组 h h h 有序也就意味着任意元素和它相邻的元素是有序的,这也就意味着整个数组已经有序了。希尔排序是第一个突破 O ( n 2 ) O(n^2) O ( n 2 ) 的排序算法。 算法流程 首先给 h h h 设置一个初始值(通常可以去数组长度的一半); 遍历数组,使得所有相隔 h h h 的元素组成的子序列有序; 更新 h h h : h = h / 2 h=h/2 h = h / 2 ,重复步骤2,直到 h < 1 h<1 h < 1 ,排序完成。 演示   图中,第一遍排序时 h = 5 h=5 h = 5 ,第二遍 h = 2 h=2 h = 2 ,第三遍 h = 1 h=1 h = 1 ,第三遍排序完成后相邻两个元素有序,因此整个数组有序。 代码实现 public static void shell_sort ( int [ ] arr

十种常见排序算法

寵の児 提交于 2019-11-29 08:58:49
1.常见排序算法分类 常见排序算法一般分为以下几种: (1)非线性时间比较类排序:交换类排序(快速排序和冒泡排序)、插入类排序(简单插入排序和希尔排序)、选择类排序(简单选择排序和堆排序)、归并排序(二路归并排序和多路归并排序); (2)线性时间非比较类排序:计数排序、基数排序和桶排序。 在比较类排序中,归并排序最快,其次是快速排序和堆排序,两者不相伯仲,但是有一点需要注意,数据初始排序状态对堆排序不会产生太大的影响,而快速排序却恰恰相反。 线性时间非比较类排序一般要优于非线性时间比较类排序,但前者对待排序元素的要求较为严格,比如计数排序要求待排序数的最大值不能太大,桶排序要求元素按照hash分桶后桶内元素的数量要均匀。线性时间非比较类排序的典型特点是以空间换时间。 注意: 本文所有示例代码均为递增排序。 2.算法描述与实现 2.1交换类排序 交换排序的基本方法是:两两比较待排序记录的排序码,交换不满足顺序要求的偶对,直到全部满足位置。常见的冒泡排序和快速排序就属于交换类排序。 2.1.1冒泡排序 算法思想: 从数组中第一个数开始,依次遍历数组中的每一个数,通过相邻比较交换,每一轮循环下来找出剩余未排序数的中的最大数并"冒泡"至数列的顶端。 算法步骤: (1)从数组中第一个数开始,依次与下一个数比较并次交换比自己小的数,直到最后一个数。如果发生交换,则继续下面的步骤,如果未发生交换

JavaScript 数据结构与算法之美 - 桶排序、计数排序、基数排序

£可爱£侵袭症+ 提交于 2019-11-29 05:59:46
1. 前言 算法为王。 想学好前端,先练好内功,只有内功深厚者,前端之路才会走得更远 。 笔者写的 JavaScript 数据结构与算法之美 系列用的语言是 JavaScript ,旨在入门数据结构与算法和方便以后复习。 之所以把 计数排序、桶排序、基数排序 放在一起比较,是因为它们的平均时间复杂度都为 O(n) 。 因为这三个排序算法的时间复杂度是线性的,所以我们把这类排序算法叫作 线性排序 (Linear sort)。 之所以能做到线性的时间复杂度,主要原因是,这三个算法不是基于比较的排序算法,都不涉及元素之间的比较操作。 另外,请大家带着问题来阅读下文,问题:如何根据年龄给 100 万用户排序 ? 2. 桶排序(Bucket Sort) 桶排序是计数排序的升级版,也采用了 分治思想 。 思想 将要排序的数据分到有限数量的几个有序的桶里。 每个桶里的数据再单独进行排序(一般用插入排序或者快速排序)。 桶内排完序之后,再把每个桶里的数据按照顺序依次取出,组成的序列就是有序的了。 比如: 桶排序利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。 为了使桶排序更加高效,我们需要做到这两点: 在额外空间充足的情况下,尽量增大桶的数量。 使用的映射函数能够将输入的 N 个数据均匀的分配到 K 个桶中。 桶排序的核心:就在于怎么把元素平均分配到每个桶里

排序算法(OC实现)

▼魔方 西西 提交于 2019-11-29 03:17:40
排序的分类: 交换类排序:冒泡排序、快速排序 插入类排序:直接插入排序、希尔排序 选择类排序:简单选择排序、堆排序 交换类排序 冒泡排序 时间复杂度:最好(有序情况下)O(n),平均(逆序情况下)O(n^2) 空间复杂度:O(1) 算法思想:(从小到大,从前往后) 第一个记录和第二个记录比较,如果第一个大,则二者交换,否则不交换;然后第二个记录和第三个记录比较,如果第二大,则二者交换,否则不交换…… 代码:(这里是创建了NSMutableArray的分类,下同) #import "NSMutableArray+Sort.h" @implementation NSMutableArray ( Sort ) /** 冒泡排序 * isAsc YES 表示升序(下同) */ - ( void )sortedArrayWithBubleASC:( BOOL )isAsc{ NSInteger len = self .count ; for ( NSInteger i=len- 1 ; i> 0 ; --i) { BOOL flag = NO ; for ( NSInteger j = 0 ; j < i; ++j) { if ((isAsc && self [j] > self [j+ 1 ]) || (!isAsc && self [j] < self [j+ 1 ])) { [

排序——01

谁说胖子不能爱 提交于 2019-11-28 21:45:35
本文主要内容: 1.插入排序 2.希尔排序 3.直接选择排序 4.堆排序 1.排序:默认情况下为非降序排序 2.稳定性:能够保证排序过程中相同的数据排序前后相对位置不变 3.插入排序:减治算法排序 每次从无序区间选择第一个数插入到有序区间的合适位置(打牌) 时间复杂度:最坏o(n的平方):完全逆序 最好o(n):完全有序[从后往前找] 一般情况:o(n的平方) 越接近有序,执行时间效率越高 空间复杂度:o(1) 稳定性:稳定 计时:long begin = System.naoTime ();long end = System.naoTime (); System.out.println(end-begin); 4.希尔排序(Shell Sort):分组进行插入排序 分组越多:大数据可以很快走到最后,每次分组排序后,数据不太有序 分组越少:每次分组排序后,数据更有序 size = 10;gap = size; gap = gap/3+1;[4,2,1] gap = gap/2;[5,2,1] 前提:利用插入排序中,数据越接近有序,时间效率越高。在插入排序之前做预排序(分组插排),使数据尽可能接近有序。 如何分组:一开始分很多组,越来越少 时间复杂度:最好:o(n) 平均:O(n 1.3,n 1.4) 最坏:O(n^2) 空间复杂度:O(1) 稳定性:不稳定

数据结构中的参见排序算法的实现,以及时间复杂度和稳定性的分析(1)

痴心易碎 提交于 2019-11-28 20:33:16
数据结构测参见算法分类如下(图片来源 https://www.cnblogs.com/hokky/p/8529042.html )   1.直接插入排序:直接插入排序是每次将要插入的数据与已排序的序列从后向前进行比较,如果已排序元素小于需要插入的数据,那么交换两者的位置,一直到达已排序序列头部为止。 代码如下: #include <iostream> using namespace std; int main() { int s[]={10,9,8,7,6,5,4,3,2,1}; for(int i=0;i<10;i++) { int j=i+1; while(s[j]<s[j-1]&&j>=1&&j<10) { int temp=s[j]; s[j]=s[j-1]; s[j-1]=temp; j--; } } for(int i=0;i<10;i++) { cout<<s[i]<<" "; } cout<<endl; return 0; } 最好情况下,序列是有序的,每次都只和有序序列的最后一个元素比较一次,此时的时间复杂度为O(n)。 最坏情况下,序列是逆序的,此时第一个元素要比较0次,第二个元素要比较1次并交换,类推下去,第n个元素要比较n-1次,并交换,此时等差数列求和,时间复杂度为O(n*2)。 稳定性分析:两个相同元素,在直接插入排序后,相对位置任然不变,算法是稳定的。

八大排序(C语言)

家住魔仙堡 提交于 2019-11-28 18:30:59
void BubbleSort();//冒泡 void SelectSort();//选择 void InsertSort();//直接插入 void ShellSort();//希尔 void HeapSort();//堆排 void QuickSort();//快排 void MegerSort();//归并 void RadixSort();//基数(桶排序) 冒泡: 1)比较相邻的元素。如果第一个比第二个大,就交换他们两个; 2)对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数; 3)针对所有的元素重复以上的步骤,除了最后一个; 4)持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。 选择: 1)首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置; 2)再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾; 3)重复第二步,直到所有元素均排序完毕。 直接插入: 插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。 算法步骤: 1)将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列; 2)从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置

排序算法

北战南征 提交于 2019-11-28 16:15:23
排序算法 排序法 最差时间分析 平均时间复杂度 稳定度 空间复杂度 冒泡排序 O(n2) O(n2) 稳定 O(1) 快速排序 O(n2) O(n*log2n) 不稳定 O(log2n)~O(n) 选择排序 O(n2) O(n2) 不稳定 O(1) 二叉树排序 O(n2) O(n*log2n) 不稳定 O(n) 插入排序 O(n2) O(n2) 稳定 O(1) 堆排序 O(n*log2n) O(n*log2n) 不稳定 O(1) 希尔排序 O O 不稳定 O(1) 堆排序 O(nlogn) O(nlogn) 不稳定 O(1) 3.排序算法的思想: (1)冒泡排序: 是相邻元素之间的比较和交换,两重循环O(n2);所以,如果两个相邻元素相等,是不会交换的。所以它是一种稳定的排序方法 (2)选择排序: 每个元素都与第一个元素相比,产生交换,两重循环O(n2);举个栗子,5 8 5 2 9,第一遍之后,2会与5交换,那么原序列中两个5的顺序就被破坏了。所以不是稳定的排序算法 (3)插入排序: 插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。刚开始这个小序列只包含第一个元素,事件复杂度O(n2)。比较是从这个小序列的末尾开始的。想要插入的元素和小序列的最大者开始比起,如果比它大则直接插在其后面,否则一直往前找它该插入的位置。如果遇见了一个和插入元素相等的