【十大经典排序算法(动图演示)】 必学十大经典排序算法

合集下载

十大经典排序算法总结

十大经典排序算法总结

⼗⼤经典排序算法总结最近⼏天在研究算法,将⼏种排序算法整理了⼀下,便于对这些排序算法进⾏⽐较,若有错误的地⽅,还请⼤家指正0、排序算法说明0.1 排序术语稳定:如果a=b,且a原本排在b前⾯,排序之后a仍排在b的前⾯不稳定:如果a=b,且a原本排在b前⾯,排序之后排在b的后⾯时间复杂度:⼀个算法执⾏所耗费的时间空间复杂度:⼀个算法执⾏完所需内存的⼤⼩内排序:所有排序操作都在内存中完成外排序:由于数据太⼤,因此把数据放在磁盘中,⽽排序通过磁盘和内存的数据传输才能进⾏0.2算法时间复杂度、空间复杂度⽐较0.3名词解释n:数据规模k:桶的个数In-place:占⽤常数内存,不占⽤额外内存Out-place:占⽤额外内存0.4算法分类1.冒泡排序冒泡排序是⼀种简单的排序算法。

它重复地⾛访过要排序的数列,⼀次⽐较两个元素,如果它们的顺序错误就把它们交换过来。

⾛访数列的⼯作是重复地进⾏直到没有再需要交换,也就是说该数列已经排序完成。

这个算法的名字由来是因为越⼩的元素会经由交换慢慢“浮”到数列的顶端1.1算法描述⽐较相邻的元素,如果前⼀个⽐后⼀个打,就交换对每⼀对相邻元素做同样的⼯作,从开始第⼀对到结尾最后⼀对,这样在最后的元素应该会是最⼤的数针对所有的元素重复以上的步骤,除了最后⼀个重复步骤1-3,知道排序完成1.2动图演⽰1.3代码实现public static int[] bubbleSort(int[] array) {if (array.length == 0)return array;for (int i = 0; i < array.length; i++)for (int j = 0; j < array.length - 1 - i; j++)if (array[j + 1] < array[j]) {int temp = array[j + 1];array[j + 1] = array[j];array[j] = temp;}return array;}1.4算法分析最佳情况:T(n) = O(n) 最差情况:T(n) = O(n2) 平均情况:T(n) = O(n2)2.选择排序表现简单直观的最稳定的排序算法之⼀,因为⽆论什么数据都是O(n2)的时间复杂度,⾸先在未排序序列中找到最⼩(⼤)元素,与数组中第⼀个元素交换位置,作为排序序列的起始位置,然后再从剩余未排序元素中继续寻找最⼩(⼤)的元素,与数组中的下⼀个元素交换位置,也就是放在已排序序列的末尾2.1算法描述1.初始状态:⽆序区为R[1..n],有序区为空2.第i躺排序开始时,当前有序区和⽆序区R[1..i-1]、R[i..n]3.n-1趟结束,数组有序化2.2动图演⽰2.3代码实现public static int[] selectionSort(int[] array) {if (array.length == 0)return array;for (int i = 0; i < array.length; i++) {int minIndex = i;for (int j = i; j < array.length; j++) {if (array[j] < array[minIndex]) //找到最⼩的数minIndex = j; //将最⼩数的索引保存}int temp = array[minIndex];array[minIndex] = array[i];array[i] = temp;}return array;}2.4算法分析最佳情况:T(n) = O(n2) 最差情况:T(n) = O(n2) 平均情况:T(n) = O(n2)3、插⼊排序是⼀种简单直观的排序算法,通过构建有序序列,对于未排序序列,在已排序序列中从后向前扫描,找到相应位置并插⼊,需要反复把已排序元素逐步向后挪位,为最新元素腾出插⼊空间3.1算法描述1.从第⼀个元素开始,该元素可以认为已经被排序2.取出下⼀个元素(h),在已排序的元素序列中从后往前扫描3.如果当前元素⼤于h,将当前元素移到下⼀位置4.重复步骤3,直到找到已排序的元素⼩于等于h的位置5.将h插⼊到该位置6.重复步骤2-53.2动图演⽰3.3代码实现public static int[] insertionSort(int[] array) {if (array.length == 0)return array;int current;for (int i = 0; i < array.length - 1; i++) {current = array[i + 1];int preIndex = i;while (preIndex >= 0 && current < array[preIndex]) {array[preIndex + 1] = array[preIndex];preIndex--;}array[preIndex + 1] = current;}return array;}3.4算法分析最佳情况:T(n) = O(n) 最坏情况:T(n) = O(n2) 平均情况:T(n) = O(n2)4、希尔排序是简单插⼊排序经过改进之后的⼀个更⾼效的版本,也称为缩⼩增量排序,同时该算法是冲破O(n2)的第⼀批算法之⼀。

[已整理]20世纪科学界十大算法

[已整理]20世纪科学界十大算法

1962 快速排序算法
不少读者恐怕和我一样,看到“快速排序算法”(Quick Sort)这个条目时,心里的感觉是——“这可总算找到组织了”。相比于其他一些对程序员而言高深莫测的数学物理公式,快速排序算法真是我们朝夕相处的好伙伴——老板让你写个排序算法,如果你写出来的不是快速排序,你都不好意思跟同事打招呼。其实根本不用自己动手实现, 不论是ANSI C,C++ STL,还是Java SDK,天下几乎所有的SDK里都能找到它的某种实现版本。
话说回来,当年这帮开发Fortran的家伙真是天才——只用23500行汇编指令就完成了一个Fortran编译器,而且其效率之高令人叹为观止:当年在IBM 主持这一项目的负责人JohnBackus在数十年后,回首这段往事的时候也感慨,说它生成代码的效率“出乎了所有开发者的想象”。看来作为程序员,自己写的程序跑起来“出乎自己的想象”,有时候还真不一定是件坏事!
快速排序的平均时间复杂度仅仅为O(Nlog(N)),相比于普通选择排序和冒泡排序等而言,实在是历史性的创举。
1965 快速傅立叶变换
如果要评选对我们的日常生活影响最大的算法,快速傅立叶变换算法应该是当仁不让的总冠军——每天当拿起话筒,打开手机,听mp3,看DVD,用DC拍照 ——毫不夸张的说,哪里有数字信号处理,哪里就有快速傅立叶变换。快速傅立叶算法是离散傅立叶算法(这可是数字信号处理的基石)的一种快速算法,它有 IBM 华生研究院的James Cooley和普林斯顿大学的John Tukey共同提出,其时间复杂度仅为O(Nlog(N));比时间效率更为重要的是,快速傅立叶算法非常容易用硬件实现,因此它在电子技术领域得到极其广泛的应用。
1946 蒙特卡洛方法
在广场上画一个边长一米的正方形,在正方形内部随意用粉笔画一个不规则的形状,呃,能帮我算算这个不规则图形的面积么?蒙特卡洛(Monte Carlo)方法便是解决这个问题的巧妙方法:随机向该正方形内扔N(N 是一个很大的自然数)个黄豆,随后数数有多少个黄豆在这个不规则几何形状内部,比如说有M个:那么,这个奇怪形状的面积便近似于M/N,N越大,算出来的值便越精确。别小看这个数黄豆的笨办法,大到国家的民意测验,小到中子的移动轨迹,从金融市场的风险分析,到军事演习的沙盘推演,蒙特卡洛方法无处不在背后发挥着它的神奇威力。

算法竞赛入门经典代码

算法竞赛入门经典代码

算法竞赛入门经典代码算法竞赛是一个旨在提高计算机编程技能和算法设计能力的竞赛活动。

对于初学者来说,入门经典代码是学习算法竞赛的重要一步。

下面是一些常见的入门经典代码。

【排序算法】在算法竞赛中,排序算法是最基础且重要的算法之一、常见的排序算法有冒泡排序、选择排序、插入排序、归并排序和快速排序等。

冒泡排序的代码如下:```cppvoid bubbleSort(int arr[], int n)for (int i = 0; i < n-1; i++)for (int j = 0; j < n-i-1; j++)if (arr[j] > arr[j+1])swap(arr[j], arr[j+1]);}}}```【查找算法】查找算法是另一个常见的算法问题。

常见的查找算法有线性查找和二分查找。

线性查找的代码如下:```cppint linearSearch(int arr[], int n, int key)for (int i = 0; i < n; i++)if (arr[i] == key)return i;}}return -1;```二分查找的代码如下:```cppint binarySearch(int arr[], int low, int high, int key)if (high >= low)int mid = low + (high - low) / 2;if (arr[mid] == key)return mid;if (arr[mid] > key)return binarySearch(arr, low, mid - 1, key);}return binarySearch(arr, mid + 1, high, key);}return -1;```【动态规划】动态规划是一种常用的解决最优化问题的算法,针对具有重叠子问题和最优子结构性质的问题进行求解。

优先级排序算法

优先级排序算法

优先级排序算法1. 优先级排序算法,听起来好高大上啊!其实呢,它就像是我们生活中的"任务管家",帮我们决定先做什么后做什么。

想象一下,你的作业、游戏时间、社交活动都在排队等你处理,这个算法就是来帮你安排这个队伍的!2. 最简单的优先级排序算法就是冒泡排序啦!它就像是在水里冒泡泡,大泡泡(高优先级的任务)会慢慢浮到顶部。

比如说,你有一堆作业:[数学, 语文, 英语, 体育]。

经过冒泡排序后,可能变成:[数学, 英语, 语文, 体育]。

数学作业像个大泡泡,"噗通"一下就浮到最前面啦!3. 接下来是选择排序,它就像是挑西瓜,每次都挑最大的(最重要的)拿出来。

想象你的待办事项是:[看电影, 写作业, 打游戏, 读书]。

用选择排序后可能变成:[写作业, 读书, 看电影, 打游戏]。

每次都选最重要的事儿放前面,简单吧?4. 插入排序就像是在整理扑克牌,你拿到一张新牌,就把它插到合适的位置。

比如你的日程安排是:[吃早餐, 上班, 开会]。

突然插入一个"紧急电话",经过插入排序可能变成:[紧急电话, 吃早餐, 上班, 开会]。

5. 快速排序是个小机灵鬼,它选一个"基准",然后把其他任务分成两组:比基准重要的和不重要的。

假设你的任务列表是:[看电影, 遛狗, 写报告, 健身, 购物]。

选"写报告"作为基准,可能最后变成:[写报告, 健身, 遛狗, 看电影, 购物]。

6. 堆排序就像是在玩"国王游戏",最大的(最重要的)总是在顶部。

想象你的待办事项是一个金字塔,最重要的事在塔尖。

每次你完成塔尖的任务,下面的任务就会争先恐后地往上爬,最重要的又会到塔尖。

7. 归并排序有点像是"分而治之"的战术。

把大问题分成小问题,解决完再合并。

比如你要安排一周的计划,可以先分别安排工作日和周末,然后再把它们合并成一个完整的周计划。

统治世界十大数学算法列表

统治世界十大数学算法列表

统治世界⼗⼤数学算法列表软件正在统治世界,⽽软件的核⼼是算法;互联⽹即将统治世界,其管理、使⽤的核⼼也是算法;算法统治着软件和互联⽹,所以说“算法统治世界”这句话应是有⼀定道理的,⽽所有算法的底层是数学原理。

什么是算法?直⽩地说,算法就是任何明确定义的计算过程,它接收⼀些值或集合作为输⼊,并产⽣⼀些值或集合作为输出。

这样,算法就是将输⼊转换为输出的⼀系列计算过程。

简⽽⾔之,我们可以说算法就是⽤来解决⼀个特定任务的⼀系列步骤(是的,不⽌计算机在使⽤算法,⼈类也同样如此)。

⽬前,⼀个有效的算法应该含有三个重要特性:它必须是有限的:如果你设计的算法永⽆休⽌地尝试解决问题,那么它是⽆⽤的。

1. 它必须是有限的它必须具备明确定义的指令:算法的每⼀步都必须准确定义,在任何场景下指令都应当没有2. 它必须具备明确定义的指令歧义。

它必须是有效的:⼀个算法被设计⽤以解决某个问题,那么它就应当能解决这个问题,并且3. 它必须是有效的仅仅使⽤纸和笔就能证明该算法是收敛的。

还有⼀个要点需要指出,算法不仅仅在计算机科学中使⽤,同时也存在于数学领域中。

事实上,⾸个被记载的数学算法要追溯到公元前1600年,古巴⽐伦⼈开发了已知最早的算法,⽤作因式分解和计算平⽅根。

这⾥,我们回答了前⾯所提到的那篇⽂章中的第⼀个问题,它认为算法是计算机范畴的实体,但如果你知晓算法这个词的真正内涵的话,真正统治世界的⼗⼤算法也能在数学书籍中找到(加法、减法、乘积等等)。

不过在这篇⽂章中,让我们将算法的定义限定在计算机算法上,所以剩下的问题是:哪⼗个算法统治了世界?在此我整理了⼀个⼩型列表,排名不分先后。

1.归并排序,快速排序和堆排序哪个排序算法最好?这取决于你的需求,这也是为什么我要将这三个使⽤频率较⾼的排序算法置于⼀处的原因。

可能你⽐较偏爱其中⼀个,但它们都是同等重要的。

归并排序算法是⽬前为⽌我们拥有的最重要的算法之⼀。

它是⼀种基于⽐较的排序算法,使⽤分治法解决那些原本复杂度为O(N^2)的问题。

各种排序方法总结

各种排序方法总结

选择排序、‎快速排序、‎希尔排序、‎堆排序不是‎稳定的排序‎算法,冒‎泡排序、插‎入排序、归‎并排序和基‎数排序是稳‎定的排序算‎法。

‎冒泡法‎:这‎是最原始,‎也是众所周‎知的最慢的‎算法了。

他‎的名字的由‎来因为它的‎工作看来象‎是冒泡:‎复杂度为‎O(n*n‎)。

当数据‎为正序,将‎不会有交换‎。

复杂度为‎O(0)。

‎直接插‎入排序:O‎(n*n)‎选择排‎序:O(n‎*n)‎快速排序:‎平均时间复‎杂度log‎2(n)*‎n,所有内‎部排序方法‎中最高好的‎,大多数情‎况下总是最‎好的。

‎归并排序:‎l og2(‎n)*n‎堆排序:‎l og2(‎n)*n‎希尔排序‎:算法的复‎杂度为n的‎1.2次幂‎‎这里我没‎有给出行为‎的分析,因‎为这个很简‎单,我们直‎接来分析算‎法:首‎先我们考虑‎最理想的情‎况1.‎数组的大小‎是2的幂,‎这样分下去‎始终可以被‎2整除。

假‎设为2的k‎次方,即k‎=log2‎(n)。

‎2.每次‎我们选择的‎值刚好是中‎间值,这样‎,数组才可‎以被等分。

‎第一层‎递归,循环‎n次,第二‎层循环2*‎(n/2)‎.....‎.所以‎共有n+2‎(n/2)‎+4(n/‎4)+..‎.+n*(‎n/n) ‎= n+n‎+n+..‎.+n=k‎*n=lo‎g2(n)‎*n所‎以算法复杂‎度为O(l‎o g2(n‎)*n) ‎其他的情‎况只会比这‎种情况差,‎最差的情况‎是每次选择‎到的mid‎d le都是‎最小值或最‎大值,那么‎他将变成交‎换法(由于‎使用了递归‎,情况更糟‎)。

但是你‎认为这种情‎况发生的几‎率有多大?‎?呵呵,你‎完全不必担‎心这个问题‎。

实践证明‎,大多数的‎情况,快速‎排序总是最‎好的。

‎如果你担心‎这个问题,‎你可以使用‎堆排序,这‎是一种稳定‎的O(lo‎g2(n)‎*n)算法‎,但是通常‎情况下速度‎要慢于快‎速排序(因‎为要重组堆‎)。

「干货」编程语言十大经典算法,你知道几个?

「⼲货」编程语⾔⼗⼤经典算法,你知道⼏个?算法与数据结构是计算机学习路上的内功⼼法,也是学好编程语⾔的重要基础。

今天给⼤家介绍⼀下⼗⼤经典算法。

⼗⼤经典算法分别是:冒泡排序,插⼊排序,选择排序,希尔排序,快速排序,归并排序,桶排序,堆排序,计数排序,基数排序。

预备知识:算法稳定性如果a==b,排序前a在b的前⾯,排序后a在b的后⾯,只要会出现这种现象,我们则说这个算法不稳定(即使两个相等的数,在排序的过程中不断交换,有可能将后⾯的b交换到a的前⾯去)。

⼀、冒泡排序冒泡排序(Bubble Sort)是基于交换的排序,它重复⾛过需要排序的元素,依次⽐较相邻的两个元素的⼤⼩,保证最后⼀个数字⼀定是最⼤的,即它的顺序已经排好,下⼀轮只需要保证前⾯n-1个元素的顺序即可。

之所以称为冒泡,是因为最⼤/最⼩的数,每⼀次都往后⾯冒,就像是⽔⾥⾯的⽓泡⼀样。

排序的步骤如下:1. 从头开始,⽐较相邻的两个数,如果第⼀个数⽐第⼆个数⼤,那么就交换它们位置。

2. 从开始到最后⼀对⽐较完成,⼀轮结束后,最后⼀个元素的位置已经确定。

3. 除了最后⼀个元素以外,前⾯的所有未排好序的元素重复前⾯两个步骤。

4. 重复前⾯ 1 ~ 3 步骤,直到都已经排好序。

例如,我们需要对数组[98,90,34,56,21]进⾏从⼩到⼤排序,每⼀次都需要将数组最⼤的移动到数组尾部。

那么排序的过程如下动图所⽰:⼆、选择排序前⾯说的冒泡排序是每⼀轮⽐较确定最后⼀个元素,中间过程不断地交换。

⽽选择排序就是每次选择剩下的元素中最⼩的那个元素,直到选择完成。

排序的步骤如下:从第⼀个元素开始,遍历其后⾯的元素,找出其后⾯⽐它更⼩的元素,若有,则两者交换,保证第⼀个元素最⼩。

对第⼆个元素⼀样,遍历其后⾯的元素,找出其后⾯⽐它更⼩的元素,若存在,则两者交换,保证第⼆个元素在未排序的数中(除了第⼀个元素)最⼩。

依次类推,直到最后⼀个元素,那么数组就已经排好序了。

20世纪十大算法


十、1987 快速多极算法
1987年,莱斯利的Greengard,和耶鲁大 学的Rokhlin发明了快速多极算法。 此快速多极算法用来计算经由引力或静电 力相互作用的N 个粒子运动的精确计算
二、1947 单纯形法
1947年,兰德公司的 George Dantzig,发明了 单纯形方法。 Dantzig提出的单纯形法便 是求解类似线性规划问题 的一个极其有效的方法。
三、1950 Krylov子空间迭代法
1950年Magnus Hestenes, Eduard Stiefel, Cornelius Lanczos发明了Krylov子空间迭 代法 Krylov子空间迭代法是用来求解形如Ax=b 的方程,A是一个n*n 的矩阵,当n充分大 时,直接计算变得非常困难,而Krylov方法 则巧妙地将其变为 KXi+1 =KXi +b-AXi 的迭代 形式来求解。
四、1951 矩阵计算的分解方法
1951年,阿尔斯通橡树岭 国家实验室的Alston Householder提出,矩阵计 算的分解方法。 这个算法证明了任何矩阵 都可以分解为三角、对角、 正交和其他特殊形式的矩 阵,该算法的意义使得开 发灵活的矩阵计算软件包 成为可能。
五、1957 优化的Fortran编译器
九、1977 整数关系探测算法
1977年:Helaman Ferguson和 伯明翰大 学的Rodney Forcade,提出了Forcade检 测算法的整数关系。 整数关系:给定—组实数X1,X2,...,Xn,是 否存在不全为零的整数a1,a2,...an,使 得:a1 x 1 +a2 x2 + . . . + an x n =0?
LOGO
20世纪十大算法Βιβλιοθήκη 一、1946 蒙特卡洛方法

各种高级排序算法集合

自底向上归并排序在所有测试的算法中速度仅次于快速排序,在 需要排序稳定性或者 O(nlogn)最坏情况时是快速排序的一个很好的替代, 但所需 O(n)的空间复杂度是对算法速度和适用范围一个严重的制约。 SGI-STL 库中 std::stable_sort()的内部实现就是自底向上归并排序。
4.原地归并排序 最好时间复杂度 O(nlogn) 平均时间复杂度 O(nlogn)
十个算法的实测效率可以分为四类讨论。
第一类为快速排序和两个非原地归并排序,这三个算法的元素比 较、移动的效率都不错,并且都有着非常紧凑的内循环,极其有效地利 用了缓存的优势,所以在实测中速度最快。
第二类为堆排序、希尔排序和 Comb Sort,这三个算法的内循环 不如第一类算法紧凑,并且希尔排序和 Comb Sort 都不是严格的
13
O(nlogn)算法,所以实测中速度慢于第一类算法。 第三类为原地归并排序和 Smooth Sort,这两个算法虽然都有着
很好的理论复杂度,但由于自身实现过于复杂,对复杂度的改进带来了 较大的常数因子,所以这类算法速度更慢。
第四类算法为 Library Sort 和 Slow Sort,这两个算法在元素的比 较和移动次数上都有很大优势,但由于这两个算法都是基于折半查找, 每次元素访问的地址相差巨大,当 n 很大时基本上无法利用缓存进行加 速,所以实测的效率最差。
5.希尔排序
最好时间复杂度 O(?)
平均时间复杂度 O(?)
最坏时间复杂度 O(?)
空间复杂度
O(1)
是否稳定

希尔排序是变步长的插入排序,利用插入排序在数据基本有序时 速度较快的特点,先用较大步长的插入排序使数据变得基本有序,再用 小步长的插入排序完成整个排序过程。

经典十大排序算法

经典⼗⼤排序算法前⾔排序种类繁多,⼤致可以分为两⼤类:⽐较类排序:属于⾮线性时间排序,时间复杂度不能突破下界O(nlogn);⾮⽐较类排序:能达到线性时间O(n),不是通过⽐较来排序,有基数排序、计数排序、桶排序。

了解⼀个概念:排序的稳定性稳定是指相同⼤⼩的元素多次排序能保证其先后顺序保持不变。

假设有⼀些学⽣的信息,我们先根据他们的姓名进⾏排序,然后我们还想根据班级再进⾏排序,如果这时使⽤的时不稳定的排序算法,那么第⼀次的排序结果可能会被打乱,这样的场景需要使⽤稳定的算法。

堆排序、快速排序、希尔排序、选择排序是不稳定的排序算法,⽽冒泡排序、插⼊排序、归并排序、基数排序是稳定的排序算法。

1、冒泡排序⼤多数⼈学编程接触的第⼀种排序,名称很形象。

每次遍历排出⼀个最⼤的元素,将⼀个最⼤的⽓泡冒出⽔⾯。

时间复杂度:平均:O(n2);最好:O(n);最坏:O(n2)空间复杂度:O(1)public static void bubbleSort(int[] arr) {/*** 总共⾛len-1趟即可,每趟排出⼀个最⼤值放在最后*/for (int i = 0; i < arr.length - 1; i++) {for (int j = 0; j < arr.length - i - 1; j++) {if (arr[j] > arr[j + 1]) {int tp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tp;}}}}2、选择排序最直观易理解的排序算法,每次排出⼀个最⼩的元素。

也是最稳定的算法,时间复杂度稳定为O(n^2)。

需要⼀个变量记录每次遍历最⼩元素的位置。

时间复杂度:O(n2)空间复杂度:O(1)public static void selectSort(int[] arr){int n = arr.length;for (int i = 0; i < n; i++) {int maxIdx = 0;for(int j = 1; j < n - i; j++){if(arr[maxIdx] < arr[j]){maxIdx = j;}}int tp = arr[maxIdx];arr[maxIdx] = arr[n - 1 - i];arr[n - 1 - i] = tp;}}3、插⼊排序⼀种直观的排序算法,从第⼆个元素开始,每次往前⾯遍历找到⾃⼰该在的位置。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

【十大经典排序算法(动图演示)】必学十大经典排序算法0.1 算法分类十种常见排序算法可以分为两大类:比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。

非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。

0.2 算法复杂度0.3 相关概念稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。

不稳定:如果a原本在b的前面,而a=b,排序之后a 可能会出现在b 的后面。

时间复杂度:对排序数据的总的操作次数。

反映当n变化时,操作次数呈现什么规律。

空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。

1、冒泡排序(Bubble Sort)冒泡排序是一种简单的排序算法。

它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。

走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。

这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

1.1 算法描述比较相邻的元素。

如果第一个比第二个大,就交换它们两个;对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;针对所有的元素重复以上的步骤,除了最后一个;重复步骤1~3,直到排序完成。

1.2 动图演示1.3 代码实现1.unction bubbleSort(arr) {2. varlen = arr.length;3. for(vari = 0; i arr[j+1]) {// 相邻元素两两对比6. vartemp = arr[j+1];// 元素交换7. arr[j+1] = arr[j];8. arr[j] = temp;9. }10. }11. }12. returnarr;13.}2、选择排序(Selection Sort)选择排序(Selection-sort)是一种简单直观的排序算法。

它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。

以此类推,直到所有元素均排序完毕。

2.1 算法描述n个记录的直接选择排序可经过n-1趟直接选择排序得到有序结果。

具体算法描述如下:初始状态:无序区为R[1..n],有序区为空;第i趟排序(i=1,2,3…n-1)开始时,当前有序区和无序区分别为R[1..i-1]和R(i..n)。

该趟排序从当前无序区中-选出关键字最小的记录R[k],将它与无序区的第1个记录R交换,使R[1..i]和R[i+1..n)分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区;n-1趟结束,数组有序化了。

2.2 动图演示代码实现function selectionSort(arr) {varlen = arr.length;varminIndex, temp;for(vari = 0; i 2.4 算法分析表现最稳定的排序算法之一,因为无论什么数据进去都是O(n2)的时间复杂度,所以用到它的时候,数据规模越小越好。

唯一的好处可能就是不占用额外的内存空间了吧。

理论上讲,选择排序可能也是平时排序一般人想到的最多的排序方法了吧。

3、插入排序(Insertion Sort)插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。

它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

3.1 算法描述一般来说,插入排序都采用in-place在数组上实现。

具体算法描述如下:从第一个元素开始,该元素可以认为已经被排序;取出下一个元素,在已经排序的元素序列中从后向前扫描;如果该元素(已排序)大于新元素,将该元素移到下一位置;重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;将新元素插入到该位置后;重复步骤2~5。

3.2 代码实现function insertionSort(arr) {varlen = arr.length;varpreIndex, current;for(vari = 1; i = 0 && arr[preIndex] > current) {arr[preIndex + 1] = arr[preIndex];preIndex--;}arr[preIndex + 1] = current;}returnarr;}3.4 算法分析插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

4、希尔排序(Shell Sort)1959年Shell发明,第一个突破O(n2)的排序算法,是简单插入排序的改进版。

它与插入排序的不同之处在于,它会优先比较距离较远的元素。

希尔排序又叫缩小增量排序。

4.1 算法描述先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,具体算法描述:选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;按增量序列个数k,对序列进行k 趟排序;每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。

仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

4.2 动图演示4.3 代码实现function shellSort(arr) {varlen = arr.length;for(vargap = Math.floor(len / 2); gap > 0; gap = Math.floor(gap / 2)) {// 注意:这里和动图演示的不一样,动图是分组执行,实际操作是多个分组交替执行for(vari = gap; i = 0 && current 4.4 算法分析希尔排序的核心在于间隔序列的设定。

既可以提前设定好间隔序列,也可以动态的定义间隔序列。

动态定义间隔序列的算法是《算法(第4版)》的合著者Robert Sedgewick提出的。

5、归并排序(Merge Sort)归并排序是建立在归并操作上的一种有效的排序算法。

该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

若将两个有序表合并成一个有序表,称为2-路归并。

5.1 算法描述把长度为n的输入序列分成两个长度为n/2的子序列;对这两个子序列分别采用归并排序;将两个排序好的子序列合并成一个最终的排序序列。

5.2 动图演示5.3 代码实现function mergeSort(arr) {varlen = arr.length;if(len 0 && right.length>0) {if(left[0]5.4 算法分析归并排序是一种稳定的排序方法。

和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(nlogn)的时间复杂度。

代价是需要额外的内存空间。

6、快速排序(Quick Sort)快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

6.1 算法描述快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。

具体算法描述如下:从数列中挑出一个元素,称为“基准”(pivot);重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。

在这个分区退出之后,该基准就处于数列的中间位置。

这个称为分区(partition)操作;递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

6.2 动图演示6.3 代码实现function quickSort(arr, left, right) {varlen = arr.length,partitionIndex,left =typeofleft !=&#39;number&#39;? 0 : left,right =typeofright !=&#39;number&#39;? len - 1 : right;if(left 7、堆排序(Heap Sort)堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。

堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

7.1 算法描述将初始待排序关键字序列(R1,R2….Rn)构建成大顶堆,此堆为初始的无序区;将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,……Rn-1)和新的有序区(Rn),且满足R[1,2…n-1]由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,……Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2….Rn-2)和新的有序区(Rn-1,Rn)。

不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。

7.2 动图演示7.3 代码实现varlen;// 因为声明的多个函数都需要数据长度,所以把len设置成为全局变量function buildMaxHeap(arr) {// 建立大顶堆len = arr.length;for(vari = Math.floor(len/2); i >= 0; i--) {heapify(arr, i);}}function heapify(arr, i) {// 堆调整varleft = 2 * i + 1,right = 2 * i + 2,largest = i;if(left arr[largest]) {largest = left;}if(right arr[largest]) {largest = right;}if(largest != i) {swap(arr, i, largest);heapify(arr, largest);}}function swap(arr, i, j) {vartemp = arr[i];arr[i] = arr[j];arr[j] = temp;}function heapSort(arr) {buildMaxHeap(arr);for(vari = arr.length - 1; i > 0; i--) {swap(arr, 0, i);len--;heapify(arr, 0);}returnarr;}8、计数排序(Counting Sort)计数排序不是基于比较的排序算法,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。

相关文档
最新文档