排序算法 基于Javascript

冒泡排序


这个是最简单的排序,就像气泡从水里冒出来。

它每执行一次外层循环,就会将最小数(或最大的)放到数组最后,然后再寻找剩余部分的最小数(或最大的)放在这一部分的最后,以此类推。

每一个外层循环的过程可以用一下图来描述:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

冒泡排序的时间复杂度为 O(n2) O ( n 2 ) O(n^2),空间复杂度为 O(1) O ( 1 ) O(1),属于 稳定 排序。适用于数据比较少或基本有序的情况。

//冒泡排序

bubbleSort = function(arr){

var len = arr.length;

for (var i = 0; i < len; i++){

for (var j = 0; j < len - i - 1; j++){

if (arr[j] > arr[j + 1])

[arr[j + 1], arr[j]] = [arr[j],arr[j + 1]];

}

}

}

选择排序


选择排序也很简单。它每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。下面是完整的选择排序过程:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

选择排序的时间复杂度为 O(n2) O ( n 2 ) O(n^2),空间复杂度为 O(1) O ( 1 ) O(1),属于 稳定 排序。适用于数据比较少的情况,综合各种情况来讲还是这个最慢。

//选择排序

selectionSort = function(arr){

var len = arr.length;

var min, min_index;//min每次找到的最小值,min_index最小值在无序序列的位置

for (var i = 0; i < len - 1; i++){

min = arr[i];

for (var j = i + 1; j < len; j++){//找到最小值

if (arr[j] < min){

min = arr[j];//找到的最小值

min_index = j;//找到的最小值索引

}

}

if (min != arr[i])

[arr[min_index], arr[i]] = [arr[i], arr[min_index]];

}

}

插入排序


这个要略微复杂一点了。它的思路就是将一个数据插入到已经排好序的有序数据中,依然保持有序。实现过程把数组看作2部分,一部分是有序的,一部分是无序的,每次大循环将无序数组的第一个元素插入到有序的数组中。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

插入排序时间复杂度为 O(n2) O ( n 2 ) O(n^2),空间复杂度为 O(1) O ( 1 ) O(1),属于 稳定 排序。算法适用于少量数据的排序。

注:二分插入和直接插入各种情况复杂度一样

//直接插入排序

insertionSort = function (arr){

var len = arr.length;

var temp;//temp每次要执行插入的值

var index;//index插入值在有序序列的位置

for (var i = 1; i < len; i++){

temp = arr[i];

for (var j = 0; j < i; j++){//找到插入位置

index = i;

if (arr[j] > temp){

index = j;//找到的插入点索引

break;

}

}

if (i != index){

for (var j = i; j > index; j–)//插入该值

[arr[j - 1], arr[j]] = [arr[j],arr[j - 1]];

}

arr[index] = temp;

}

}

快速排序


这个想必大家都耳熟能详,20世纪十大经典算法之一。主要原因还是它极大的推动了信息技术的发展,可惜它不是稳定算法。

这个算法比较就比较难理解了,它通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的任一数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。这里面包含的分治的思想。

下面一个图表现了函数的一次执行过程:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

而这个图表现了整个排序过程:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

插入排序时间复杂度为 O(nlogn) O ( n l o g n ) O(nlogn),空间复杂度为 O(logn) O ( l o g n ) O(logn),属于 不稳定 排序。

快速排序(前轴)

function quickSort(arr){

qSort(0, arr.length - 1);

return arr;

function qSort(left, right){

if (left >= right)//两个数相遇则结束该轮排序

return;

var key = arr[left];//取最左边的元素作为标识数

var i = left;

var j = right;

while (i != j){//两个数相遇则结束该轮排序

while (i != j && arr[j] >= key) j–;//j前移

[arr[j], arr[i]] = [arr[i], arr[j]];

while (i != j && arr[i] <= key) i++;//i后移

[arr[j], arr[i]] = [arr[i], arr[j]];

}

qSort(left, j - 1);//对标识数前面的数继续该方法排序

qSort(j + 1, right);//对标识数后面的数继续该方法排序

}

}

这里补充一下:快速排序由于其实轴的选择不同,分为前轴、中轴、后轴快速排序,上面的例子是前轴快速排序,下文比较算法的时候也才用上述代码。不过,这里补充另外2种代码:

//中轴快速排序

function quickSortM(arr){

qSort(0, arr.length - 1);

return arr;

function qSort(left, right){

if (left < right){

var index = Math.floor((left + right) / 2);

var key = arr[index];

var i = left - 1;

var j = right + 1;

while (true){

while (arr[++i] < key); // 向右找大于轴的数

while (arr[–j] > key); // 向左找小于轴的数

if (i >= j)//两索引相同结束排序

break;

[arr[i], arr[j]] = [arr[j],arr[i]];//交换找到的数

}

qSort(left, i - 1); // 继续这样对轴前面的排序

qSort(j + 1, right); // 继续这样对轴后面的排序

}

}

}

//后轴快速排序

function quickSortB(arr){

qSort(0, arr.length - 1);

return arr;

function qSort(left, right){

if (left >= right)//两索引相同结束排序

return;

var key = arr[right];

var i = left - 1;//s是最右边的轴

for (var j = left; j < right; j++){ //将数据分成大于轴和小于轴两部分

if (arr[j] <= key){

i++;

[arr[i], arr[j]] = [arr[j],arr[i]];

}

}

i++;

[arr[right], arr[i]] = [arr[i],arr[right]];//将轴插入到大于轴和小于轴两部分的中间

qSort(left, i - 1);//继续这样对轴前面的排序

qSort(i, right);//继续这样对轴后面的排序

}

}

归并排序


这个排序在小编眼里用的是最广泛的,很多函数封装内部都才用这个排序,包括数据库在内的排序也采用了归并排序或红黑树的形式。这个排序也用到了分治的思想:它将一个序列逐级拆分成小序列,将小序列排序后合并,得到完全有序的序列。若每次将序列分成2个子序列,再依此合并,称为二路归并。

没理解?看图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

插入排序时间复杂度为 O(nlogn) O ( n l o g n ) O(nlogn),空间复杂度为 O(n) O ( n ) O(n),属于 稳定 排序。

//归并排序

function mergeSort(arr){

var temp = [];

merge(0, arr.length - 1);

return arr;

function merge(left, right){//temp是临时空间,存放排序过程中间结果

var mid;//该部分中间位置

if (left >= right)//分组小于等于1时归并结束

return;

mid = Math.floor((left + right) / 2);

merge(left, mid);//对中间位置之前部分继续该方法排序

merge(mid + 1, right);//对中间位置之后部分继续该方法排序

var i = left, j = mid + 1, k = left;

while (i != mid + 1 && j != right + 1)//比较两部分每个值,把较小的放入temp中,并后移该指针,直到某部分全部遍历

temp[k++] = arr[i] < arr[j] ? arr[i++] : arr[j++];

//将未全部遍历部分数据顺次放入temp中

while (i != mid + 1)

temp[k++] = arr[i++];

while (j != right + 1)

temp[k++] = arr[j++];

//将temp复制会a中

for (i = left; i <= right; i++)

arr[i] = temp[i];

}

}

希尔排序


这是惟一一个用人名命名的排序算法。它把数据按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

这个估计最不好理解了,看看图吧:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

希尔排序时间复杂度为 O(n13) O ( n 1 3 ) O(n^\frac1{3}),空间复杂度为 O(1) O ( 1 ) O(1),属于 不稳定 排序。

//希尔排序

shellSort = function(arr){

var len = arr.length;

var index = Math.floor(len / 2);//得到比较步长

var j, temp;

while (index > 0){

for (var i = index; i < len; i++){//遍历起点后移,保证每个数在该步长下参与且只参与1此排序

temp = arr[i];

for (j = i; j >= index && arr[j - index] > temp;){//等步长数列执行插入排序

arr[j] = arr[j - index];

j -= index;

arr[j] = temp;

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)


核心竞争力,怎么才能提高呢?

成年人想要改变生活,逆转状态?那就开始学习吧~

万事开头难,但是程序员这一条路坚持几年后发展空间还是非常大的,一切重在坚持。

为了帮助大家更好更高效的准备面试,特别整理了《前端工程师面试手册》电子稿文件。

前端面试题汇总

JavaScript

性能

linux

前端资料汇总

完整版PDF资料免费分享,只需你点赞支持,动动手指点击此处就可免费领取了

前端工程师岗位缺口一直很大,符合岗位要求的人越来越少,所以学习前端的小伙伴要注意了,一定要把技能学到扎实,做有含金量的项目,这样在找工作的时候无论遇到什么情况,问题都不会大。

log.csdnimg.cn/img_convert/7796de226b373d068d8f5bef31e668ce.png)

性能

linux

前端资料汇总

完整版PDF资料免费分享,只需你点赞支持,动动手指点击此处就可免费领取了

前端工程师岗位缺口一直很大,符合岗位要求的人越来越少,所以学习前端的小伙伴要注意了,一定要把技能学到扎实,做有含金量的项目,这样在找工作的时候无论遇到什么情况,问题都不会大。

  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值