js解析常见排序算法

来自:    更新日期:早些时候
~ 冒泡排序基本思想

相信大家也看过在水中的冒泡现象,从下至上,气泡会越来越大,而所谓冒泡排序,也是建立在这个原理上,即从下至上按照一定的顺序,进行排列。

相邻的元素,依次进行对比,如果第一个元素大于第二个元素,那么交换位置。而经过一轮比较之后,最大的元素就会“冒泡”到队尾,之后对已经排好序的元素不予理会,对未排序的元素继续这个步骤,在第n-1(n为数组元素个数)轮之后,完成排序。

代码实现functionbubbleSort(nums){for(leti=0;i<nums.length-1;i++){for(letj=0;j<nums.length-1-i;j++){if(nums[j]>nums[j+1]){lettemp=nums[j]nums[j]=nums[j+1]nums[j+1]=temp}}}returnnums}

复杂度

冒泡排序是一种稳定的排序方法,其平均时间复杂度为O(n^2),最好情况的时间复杂度为O(n),最坏情况的时间复杂度为O(n^2),在排序过程当中只需要一个元素的辅助空间,也就是temp,所以空间复杂度为O(1)

例题分析letnums=[3,6,4,2,11,10,5]

第一轮排序:3与6比较之后,不交换,6和4交换位置,之后6再次与2比较,仍然需要进行位置交换,然后继续类似的操作,11就到了末尾,排序之后数组为【3,4,2,6,10,5,11】

第二轮排序:3与4比较不进行位置交换,这个时候我们从上帝视角发现,10为最大元素,那么这个时候10会一直冒泡到11的前一位元素上。结果为【3,2,4,6,5,10,11】

后续操作类似,直到四轮排序结束后,数组变为有序数组

图例如下:

选择排序基本思想

选择排序算法,顾名思义,选择两个字至关重要,首先元素之间进行对比,使用min来记录当前最小元素的下标索引,与首元素交换,也就是排列在数组的起始位置,之后在剩下未排序的数组元素当中又通过这种方式选择出一个最小的元素,在经过n-1轮排序后,数组变为有序数组。

代码实现functionselectionSort(nums){for(leti=0;i<nums.length-1;i++){letmin=ifor(letj=i+1;j<nums.length;j++){if(nums[j]<nums[min])min=j//保存最小值的下标索引}lettemp=nums[i]nums[i]=nums[min]nums[min]=temp}returnnums}

复杂度

选择排序是一种不稳定的排序方法,其平均时间复杂度为O(n^2),最好最坏的情况时间复杂度都为O(n^2),在排序过程当中只需要一个元素的辅助空间,所以空间复杂度为O(1)

例题分析letnums=[7,4,5,9,8,2,1]

第一轮排序:第一个元素与其余元素进行比较,找出最小值的下标索引,保存第一个元素的下标为min,之后分别与各个元素进行比较,此时1为最小值,保存min,然后与元素7进行交换,排序完之后为【1,4,5,9,8,2,7】

第二轮排序:元素4与其余未排序元素进行比较,最后与2交换位置,排序之后,数组为【1,2,5,9,8,4,7】

之后依次按照这个方法寻找未排序的最小元素,4轮之后最终变为有序数组

插入排序基本思想

在插入第i个记录时候,R0至R1是有序的,那么将nums[i]与这些元素进行比较,找到应该插入的位置,在插入的位置之后的元素都需要依次向后移动

默认第一个元素是存在顺序的,那么从第二个元素开始,需要依次进行比较,将该元素从后往前开始比较,如果比当前元素大,那么将该元素后移,直到找到一个比该元素更小的元素,然后将该元素放在当前元素后面。如此反复,即可排序成功

代码实现functioninsertionSort(nums){for(leti=1;i<nums.length;i++){for(letj=i;j>0;j--){if(nums[j]<nums[j-1]){lettemp=nums[j];nums[j]=nums[j-1];nums[j-1]=nums;}}}returnnums;}

这么一瞅,是不是有点像冒泡排序

还有第二种,但是第二层循环我用了var关键字来声明,因为let块级作用域的原因,nums[j+1]=temp这一行代码会访问不到变量j,所以我用var来声明,但是无伤大雅,这里也可以用while循环来做的,网友们可自行琢磨

functioncharu(nums){for(leti=1;i<nums.length;i++){if(nums[i]<nums[i-1]){lettemp=nums[i]//保存nums[i]nums[i]=nums[i-1]for(varj=i-1;j>=0&&nums[j]>temp;j--)nums[j+1]=nums[j]nums[j+1]=temp}}returnnums;}

复杂度

插入排序是一种稳定的排序方法,其平均时间复杂度为O(n^2),最好情况的时间复杂度为O(n),最坏情况的时间复杂度为O(n^2),在排序过程当中只需要一个元素的辅助空间,所以空间复杂度为O(1)

例题分析letnums=[5,7,4,6,3,1,2,9,8]

默认第一个元素5是有序的,那么从第二个元素开始,5会先与7比较,此时按兵不动,而后比较4会插入5的前面,依次类推,就可以得到有序数组

希尔排序基本思想

希尔排序又被称为“缩小增量排序”,这是对插入排序算法的改进

首先将整个待排序序列分为若干子序列,然后分别进行直接插入排序,待整个序列中的记录基本有序时,再对全体序列进行一次插入排序

先取一个小于n的整数d1作为第一个增量,将数组分为d1个组,即所有距离为d1倍数序号的记录放在同一个组当中,在各组当中进行插入排序。

然后取d2(d2<d1)重复上述分组和排序工作

直到所取的增量为di=1,所有记录都在同一组然后进行插入序列为止一般取的都是d1=n/2?d2=2/d1,依次类推

代码实现functionshellSort(nums){lethalf=parseInt(nums.length/2);//设置增量为原数组长度的一半for(letgap=half;gap>=1;gap=parseInt(gap/2)){for(leti=gap;i<nums.length;i++){for(letj=i-gap;j>=0;j=j-gap){if(nums[j]>nums[j+gap]){lettemp=nums[j];nums[j]=nums[j+gap];nums[j+gap]=temp;}}}}returnnums}

复杂度

希尔排序也是一种不稳定的排序方法,其平均时间复杂度约为O(nlogn^2),约为O(n^1.3),最好情况的时间复杂度为O(n),最坏情况的时间复杂度为O(n^2),在排序过程当中只需要一个元素的辅助空间,所以空间复杂度为O(1)

例题分析

因为这里数量太少不利于讲解,我换个例子

letnums=[9,1,2,5,7,4,8,6,3,5]

我们就取d1=5(n/2)、d2=3(d1/2)、d3=2(d2/2),d4=1来作为排序的增量,依据情况而定上下取整

第一轮排序:按照d1=5,进行分组,那么9和4为一组,1和28,2和6,5和3,7和5两两配对,那么此时就需要比较元素之间的大小,各组之间进行插入排序,那么第一轮排序后,数组为【4,1,2,3,5,9,8,6,5,7】

第二轮排序:按照d2=3,进行分组,那么4、3、8、7为一组,1、5、6以及2、9、5各成一组,插入排序后,数组为【3,1,2,4,5,5,7,6,9,8】

第三轮排序:按照d3=2,j进行分组,也就是相邻元素不为一组,3,2,5,7,9为一组,1,4,5,6,8为一组,那么两组内部进行插入排序后,数组为【2,1,3,4,5,5,7,6,9,8】

第四轮排序:直接取d4=1,全部序列进行插入排序,得到最后的结果【1,2,3,4,5,5,6,7,8,9】

其实实际当中不用四轮,三轮即可,只要向下取整就好。

快速排序基本思想

通过一趟排序将待排序的元素划分为独立的两个部分,称为前半区和后半区,其中前半区的元素都不大于后半区元素,然后再分别对这两部分进行快速排序,从而使整个序列有序

附设两个指针变量i和j,分别指向序列第一个元素和最后一个元素,设第一个关键字为pivot,从j的位置向前检索找到第一个小于pivot的元素,将该元素向前移动到i指示的位置,从i所指的位置向后搜索,找到第一个大于pivot的元素将该元素移动到j所指的位置,重复过程直到i、j相遇

代码实现functionPartition(nums,low,high){vari=low,j=high,pivot=nums[i];while(i<j){//从右往左找while(i<j&&nums[j]>pivot)j--;if(i<j){swap(i++,j,nums);}//从左往右找while(i<j&&nums[i]<=pivot)i++;if(i<j){swap(i,j--,nums);}}returni;//返回基准元素位置}functionswap(a,b,nums){console.log(a,b,nums[a],nums[b])vartemp=nums[a];nums[a]=nums[b];nums[b]=temp;}functionQuickSort(nums,low,high){varmid;if(low<high){mid=Partition(nums,low,high);//返回基准元素位置QuickSort(nums,low,mid-1);//左边快速排序QuickSort(nums,mid+1,high);//右边快速排序}}QuickSort(nums,0,nums.length-1);

复杂度

快速排序是一种不稳定的排序方法,其平均时间复杂度为O(nlog2n),最好情况的时间复杂度为O(nlog2n),最坏情况的时间复杂度为O(n^2),空间复杂度为O(nlog2n)

例题分析

我从网上找了个例子,相信大家更容易看懂,哈哈哈

重点就是对双指针解法的理解程度,需要在j指针找到比i指针更小的元素,进行替换

归并排序基本思想

归并其实利用的是一个递归的思想,将长度为n的整个数组看成是n个长度为1的多个数组,对这些数组进行两两归并,得到n/2个长度为2或者1的有序数组,之后再两两归并,重复这个步骤,直到所有的元素都形成长度为n的数组。

大致步骤如下:

把n个记录看成n个长度为l的有序子表

进行两两归并使记录关键字有序,得到n/2个长度为2的有序子表

重复第2步直到所有记录归并成一个长度为n的有序表为止。

具体操作为不断切割数组,类似于对半切,不断的在中间元素切割,使得各个数组一分为二,最终变为n个长度为1的数组,之后再两两合并这些元素,形成一个有序链表。

代码实现letnums=[3,6,4,2,11,10,5]0

复杂度

归并排序是一种稳定的排序方法,其平均时间复杂度为O(n^2),最好情况的时间复杂度为O(nlog2n),最坏情况的时间复杂度为O(nlog2n),在排序过程当中只需要n个元素的辅助空间,所以空间复杂度为O(nlogn)

例题分析

大致步骤如下:

堆排序基本思想

若将序列对应的一维数组看成是一个完全二叉数?,完全二叉树中所有非终端节点的值均不小于(或者不大于)其左右孩子节点的值,因此在一个堆中,堆顶元素,即完全二叉树的根节点必然为序列中的最大元素或者是最小元素,并且堆中的任一一棵子树也都是堆,若堆顶为最小元素,则称为小根堆落;堆顶为最大元素,则称为大根堆。

对一组待排序记录的元素首先按堆的定义排成一个序列,即建立初始堆,从而可以输出堆顶的最大元素(对于大根堆而言),?然后将剩余的元素再调整成新堆,便得到次大的元素,如此反复,直到全部元素排成有序序列为止?

写代码前,需要知道这些基本知识

Parent(i)=floor((i-1)/2),i的父节点下标

Left(i)=2i+1,i的左子节点下标

Right(i)=2(i+1),i的右子节点下标

代码实现letnums=[3,6,4,2,11,10,5]1

复杂度

堆排序是一种不稳定的排序方法,其平均时间复杂度为O(nlog2n),最好情况的时间复杂度为O(nlog2n),最坏情况的时间复杂度为O(nlog2n),在排序过程当中只需要一个元素的辅助空间,所以空间复杂度为O(1)

例题分析

这里我也是偷个懒,我感觉说的可能不明白,让读者们看图说话吧!

原文:https://juejin.cn/post/7096029648026337287


js解析常见排序算法视频

相关评论:
  • 13733331801js解析常见排序算法
    庞叶华选择排序算法,顾名思义,选择两个字至关重要,首先元素之间进行对比,使用min来记录当前最小元素的下标索引,与首元素交换,也就是排列在数组的起始位置,之后在剩下未排序的数组元素当中又通过这种方式选择出一个最小的元素,在经过n-1轮排序后,数组变为有序数组。代码实现functionselectionSort(nums){for(leti=0;i<n...

  • 13733331801JavaScript实现十大排序算法(图文详解)
    庞叶华解法functionquickSort(arr){sort(arr,0,arr.length-1);returnarr;functionsort(arr,low,high){if(low>=high){return;}leti=low;letj=high;constx=arr[i];\/\/取出比较值x,当前位置i空出,等待填入while(i<j){\/\/从数组尾部,找出比x小的数字while(arr[j]>=x&&i<j){j--;}\/\/将空出的位置,填入当前...

  • 13733331801选择排序js?
    庞叶华内排序:所有排序操作都在内存中完成; 外排序:由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行; 时间复杂度:一个算法执行所耗费的时间。 空间复杂度:运行完一个程序所需内存的大小。 (2)排序算法图片总结: 1.冒泡排序: 解析:1.比较相邻的两个元素,如果前一个比后一个大,则交换位置。

  • 13733331801【JavaScript】JS常见排序方法
    庞叶华进阶算法如归并排序,它采用分治法,将数组不断对半划分,然后合并有序部分。虽然抽象,但其时间复杂度为O(n*logN),在分治过程中,每次划分和合并的时间分别对应为O(n)和O(logN),整体上更为高效。快速排序是另一种常用排序方式,chrome的数组sort方法就基于快速排序,通过分区操作和递归,分区时间复杂...

  • 13733331801js数组冒泡排序?
    庞叶华JS常见排序算法1、数据结构算法中排序有很多种,常见的、不常见的,至少包含十种以上。根据它们的特性,可以大致分为两种类型:比较类排序和非比较类排序冒泡排序是一次比较两个元素,如果顺序是错误的就把它们交换过来。2、即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个...

  • 13733331801js sort原理
    庞叶华js提供了sort方法,方便对数组进行排序,然而不同引擎对js的sort方法解析可能存在差异。本文基于v8引擎进行分析。在v8引擎中,对sort方法提供了2种排序算法:插入排序及快排序。sort使用方法:当没有参数传入的时候,其排序顺序默认为,将待排序数据转换为字符串,并按照 Unicode 序列排序;当然,比较函数...

  • 13733331801JS排序之冒泡排序以及写法?
    庞叶华时间复杂度指的是一个算法执行所耗费的时间 空间复杂度指运行完一个程序所需内存的大小 稳定指,如果a=b,a在b的前面,排序后a仍然在b的前面 不稳定指,如果a=b,a在b的前面,排序后可能会交换位置 原理 依次比较相邻的两个值,如果后面的比前面的小,则将小的元素排到前面。依照这个规则进行多次...

  • 13733331801什么是js冒泡排序
    庞叶华js冒泡排序是一种计算机科学领域的较简单的排序算法。它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行,直到没有相邻元素需要交换,也就是说该元素列已经排序完成。这个算法的名字由来是因为越小的元素会...

  • 13733331801web前端javascript能实现什么算法或者计算
    庞叶华在Web开发中,JavaScript很重要,算法也很重要。下面整理了一下一些常见的算法在JavaScript下的实现,包括二分法、求字符串长度、数组去重、插入排序、选择排序、希尔排序、快速排序、冒泡法等等。仅仅是为了练手,不保证高效与美观,或许还有Bug,有时间再完善吧。1.二分法:function binary(items,value){ va...

  • 13733331801排序算法
    庞叶华实现sort排序(将正整数数组从小到大排序)排序算法\\思路:1'用递归实现、2'用循环实现 递归思路选择排序\\例1.将长度为2的数组排序 例2.将长度为3的数组排序\\思路:先求最小值,把最小值放前面。\\然后将后面2个数字进行"2个数的排序"。let?minIndex?=?(numbers)?=>?numbers.indexOf(min(numbers)...

  • 相关主题精彩

    版权声明:本网站为非赢利性站点,内容来自于网络投稿和网络,若有相关事宜,请联系管理员

    Copyright © 喜物网