javascript快速排序算法,javascript排序函数

  javascript快速排序算法,javascript排序函数

  本文已经为大家带来了一些关于javascript的知识,主要介绍了JavaScript实现十大排序算法的相关问题,包括冒泡排序、选择排序、插入排序等等。来看看吧,希望对你有帮助。

  【相关推荐:javascript视频教程,web前端】

  

冒泡排序

  

排序的效果图

  

解法

  气泡分类的特征在于用于处理的数字。I号需要和后面的len-i-1号一一对比。

  为什么是“len-I-1”号?

  因为数组末尾的I的个数已经按顺序排好了,所以确认位置不变。

  为什么要确保位置一致?因为在它们被固定之前,它们已经被逐一与之前的数字进行了比较。

  函数bubbleSort(arr){

  const len=arr .长度;

  for(设I=0;I len-1;i ){

  for(设j=0;j len-I-1;j ){

  if(arr[j] arr[j 1]){

  const tmp=arr[j 1];

  arr[j 1]=arr[j];

  arr[j]=tmp;

  }

  }

  }

  返回arr

  }

快速排序

  

概要

  快速排序,利用分治法的思路。

  通过选择一个数字作为比较值,将其他要排序的数字分为两部分:比较值比较值。并重复此步骤,直到只有要排序的数字是自己,排序完成。

  

效果图

  

解法

  函数快速排序(arr){

  排序(arr,0,arr . length-1);

  返回arr

  函数排序(arr,low,high){

  if(低=高){

  返回;

  }

  设i=低;

  设j=高;

  const x=arr[I];//取出比较值X,当前位置I是空的,等待填充。

  while(i j){

  //从数组末尾开始,查找小于x的数字。

  while(arr[j]=x i j){

  j-;

  }

  //填充空出位置的当前值,空出下标j位置。

  //ps:比较值已经缓存在变量x中。

  如果(i j){

  arr[i]=arr[j]

  我;

  }

  //从数组的开头,找出大于x的数。

  while(arr[i]=x i j){

  我;

  }

  //在下标j中填入数字,下标I突出。

  如果(i j){

  阵列[j]=阵列[i]

  j-;

  }

  //循环,直到左右指针I,J相遇,

  //当我们相遇时,i==j,所以下标I的位置是空的。

  }

  arr[I]=x;//将缓存的数X中空出的位置填满,一轮排序完成。

  //分别递归排序剩余的两个区间

  sort(arr,low,I-1);

  sort(arr,i 1,high);

  }

  }

希尔排序

  

概要

   Hill排序是插入排序算法,是简单插入排序改进后更高效的版本。它是由唐纳德谢尔在1959年提出的。

  其特征是用增量将数组分成多组子序列,然后插入并排序子序列。

  因为增量由大到小递减,所以也叫缩小增量排序

  

效果图

  

解法

  插入时使用互换方法。

  函数shellSort(arr){

  //分组规则gap/2递减。

  for(设gap=math . floor(arr . length/2);差距0;gap=Math.floor(gap/2)){

  for(设i=gap长度;i ){

  设j=I;

  //组中的数字,执行插入排序,

  //下标大的数小于下标小的数时交互。

  //这里注意,一组中的数字并不是一次全部比较的,I需要逐渐增大才能包含下一组中的数字。

  while(j-gap=0 arr[j]arr[j-gap]){

  swap(j,j-gap);

  j=j-gap;

  }

  }

  }

  返回arr

  功能交换(a,b){

  const tmp=arr[a];

  arr[a]=arr[b];

  arr[b]=tmp;

  }

  }插入时,使用move方法。

  函数shellSort(arr){

  for(设gap=math . floor(arr . length/2);差距0;gap=Math.floor(gap/2)){

  for(设i=gap长度;i ){

  设j=I;

  const x=arr[j];//缓存号码,空出位置。

  while(j - gap=0 x arr[j-gap]){

  arr[j]=arr[j-gap];//在空缺的位置填写符合条件的数字。

  j=j-gap;

  }

  arr[j]=x;//最后将缓存的号码填充到空缺的位置。

  }

  }

  返回arr

  }

选择排序

  

排序的效果图

  

解法

  功能选择排序(arr){

  const len=arr .长度;

  for(设I=0;I len-1;i ){

  设minIndex=I;

  for(设j=I ^ 1;j lenj ){

  if(arr[j] arr[minIndex]){

  minIndex=j;//保存最小数量的下标

  }

  }

  const tmp=arr[I];

  arr[I]=arr[minIndex];

  arr[minIndex]=tmp;

  }

  返回arr

  }

归并排序

  

概要

  合并和排序。利用分治的思想,把大数组分解成小数组,直到单个元素。然后用选择排序的方法,回溯拆分的小数组,按顺序合并,直到合并成大数组。

  

效果图

  

小数组合并的过程

  

解法

  函数mergeSort(arr){

  返回sort(arr,0,arr . length-1);//注意右边的区间是arr.length-1

  //排序方法,递归。

  函数排序(arr,left,right){

  //离开的时候!==对,证明没有拆分到最小元素。

  如果(左/右){

  //取中间值并将其分成两个小数组

  const mid=Math.floor((左右)/2);

  const leftArr=sort(arr,left,mid);

  const rightArr=sort(arr,mid 1,right);

  //递归合并

  返回merge(leftArr,rightArr)

  }

  //left==right,已经是最小的元素了,直接返回就好。

  向左返回=0?[arr[left]]:[];

  }

  //合并两个有序数组

  函数合并(leftArr,rightArr){

  让left=0;

  让right=0;

  const tmp=[];

  //使用双指针扫描两个数组

  while(left left arr . length right arr . length){

  if(left arr[left]=right arr[right]){

  tmp . push(left arr[left]);

  }否则{

  tmp . push(right arr[right]);

  }

  }

  //合并剩余的内容

  if(left leftArr.length){

  while(left leftArr.length){

  tmp . push(left arr[left]);

  }

  }

  if(right rightArr.length){

  while(right rightArr.length){

  tmp . push(right arr[right]);

  }

  }

  返回tmp

  }

  }

插入排序

  

排序的效果图

  

解法

  函数插入排序(arr){

  const len=arr .长度;

  //注意,I从1开始

  for(设I=1;我leni ){

  设preIndex=I-1;

  设current=arr[I];

  //在位置I之前,有已经排序的数字。while用于找到一个坑并插入当前数current。

  while(preIndex=0 arr[preIndex]current){

  arr[pre index 1]=arr[pre index];//对于大于current的值,向后移动一位,为插入current腾出空间

  preIndex-;

  }

  arr[preIndex 1]=当前;

  }

  返回arr

  }

堆排序

  

概要

  逻辑结构表示如下:

  物理数据层处的表示如下:

  堆排序是选择排序的优化版本,使用数据结构——树来管理数据。

  以大顶队为例:

  通过建造一个大的顶部桩

  取出堆顶的最大数,与堆底的叶节点交换。

  然后,树剪掉最大数量的叶子。

  再次调堆,再次变成大顶堆。

  回到步骤2,重复这个循环,直到所有的数字都被取出。

  

效果图

  建造大顶桩

  从第一个非叶节点开始,调整它的子树。

  调整下标1节点的子树后,继续向上调整其父节点(下标0)的子树。

  最后完成整树调整,搭建大顶桩。

  把最上面的最大值一个一个拿出来。

  将顶号与最后一个叶号交换,提取顶号9。

  至此,数字9的位置就固定了,树把数字9所在的叶子剪掉。然后,重建大顶桩。

  顶桩建好后,继续抽出顶号8,再重新建好顶桩。

  最后,所有的节点都被画出来,这意味着排序完成。

  

解法

  函数堆排序(arr){

  //第一次构建一个大的顶堆

  for(让I=math . floor(arr . length/2)-1;I=0;我- ){

  //开头的第一个节点是树的最后一个非叶节点

  //从建立一个子树开始,逐步调整

  buildHeap(arr,I,arr . length);

  }

  //逐个取出堆顶的最大值。

  for(设j=arr . length-1;j 0;j - ){

  swap(arr,0,j);//提取堆顶的值(下标0),与最后一个叶节点交换。

  //重建大顶堆

  //由于上一步堆顶的最大值已经交换到数组末尾,所以它的位置是固定的。

  //要比较的数组是左数组,长度是J,所以这里的值是length==J。

  buildHeap(arr,0,j);

  }

  返回arr

  //建立一个大的顶部堆

  函数构建堆(arr,I,length){

  设tmp=arr[I];

  for(设k=2 * I 1;k长度;k=2 * k ^ 1){

  //先判断左右叶节点,哪个更大。

  if(k 1长度arr[k 1] arr[k]){

  k;

  }

  //将最大的叶节点与当前值进行比较

  if(arr[k] tmp){

  //k节点的值大于I节点的值,需要交换。

  arr[I]=arr[k];//将K节点的值与I节点的值交换

  I=k;//注意:交换后当前值tmp的下标是K,需要更新。

  }否则{

  //如果tmp大于左右子节点,其子树小于当前值无需判断。

  打破;

  }

  }

  //i是交换后的下标,更新为tmp。

  arr[I]=tmp;

  }

  //交换值

  函数交换(arr,I,j){

  const tmp=arr[I];

  arr[I]=arr[j];

  arr[j]=tmp;

  }

  }

计数排序

  

概要

  计数排序的要点是开辟一个由连续网格组成的空间来存放数据。

  依次读取数组中的数字,并存储在与其值对应的下标中。

  存储完成后,按照空间顺序依次读取每个网格的数据,然后输出。

  所以,计数排序要求排序的数据,必须是有范围的整数

  

效果图

  

解法

  函数计数排序(arr){

  设maxValue=Number。最小值;

  设minValue=Number。MAX _ VALUE

  设offset=0;//位移,用于处理负数

  const result=[];

  //取出数组的最大值和最小值

  arr.forEach(num={

  maxValue=num maxValue?num:max value;

  minValue=num minValue?minValue:num;

  });

  if(最小值0){

  offset=-minValue;

  }

  const bucket=新数组(最大值偏移量1)。填充(0);//初始化连续网格

  //根据值将数组中的每个数字放入对应的下标中,

  //` bucket [num]==n `网格的含义:有n个数值,数值为num。

  arr.forEach(num={

  bucket[数量偏移量];

  });

  //读取网格中的数字

  bucket.forEach((store,index)={

  while(store - ){

  result.push(索引偏移量);

  }

  });

  返回结果;

  }

桶排序

  

概要

  桶排序是计数排序的优化版,原理是一样的:以空间换时间,分而治之。

  对数组分组,减少排序次数,对子数组排序,最后合并得到结果。

  

效果图

  

解法

  函数bucketSort(arr,bucketSize=10){

  //bucketSize每个桶中可以存储的数字范围(0,9)

  if(arr.length=1){

  返回arr

  }

  设max value=arr[0];

  设minValue=arr[0];

  假设结果=[];

  //取出数组的最大值和最小值

  arr.forEach(num={

  maxValue=num maxValue?num:max value;

  minValue=num minValue?minValue:num;

  });

  //初始化桶的数量

  const bucket count=math . floor((max value-minValue)/bucket size)1;//桶的数量

  //初始化桶的容器

  //注意这里的js语法,不能直接填充([]),因为生成的2D下标数组是同一个地址。

  const buckets=新数组(bucketCount)。填充(0)。map(()=[]);

  //根据映射规则将数字放入桶中。

  arr.forEach(num={

  const bucket index=math . floor((num-minValue)/bucket size);

  桶[桶指数]。推送(num);

  });

  //遍历存储在每个桶中的数字

  buckets.forEach(store={

  //如果桶中只有一个数,或者桶为空,或者两者都是重复数,则直接合并到结果中。

  if(store . length=1 bucket size==1){

  result=result . concat(store);

  返回;

  }

  //递归,把桶里的数字再分成不同的桶。

  const subSize=math . floor(bucket size/2);//减少桶中的编号间隔,但必须至少为1。

  const tmp=bucketSort(store,subSize=1?1:subSize);

  result=result . concat(tmp);

  });

  返回结果;

  }

基数排序

  

概述

  基数排序,一般是从右到左,比较小数位数,存放在[0,9]的10个桶中,进行排序。

  从低位开始比较,逐位比较,这样就可以把每个十进制位上的数字(一、十、一百、一千、一万)放入对应的桶中,形成偏序。

  为什么是10桶?

  因为十进制数是由0-9位数组成的,小数点上对应的位数都会落在这个范围内,所以是10桶。

  有两种方法对基数进行排序:

  MSD从上往下排序。

  LSD从低位开始排序。

  

效果图

  

解法

  函数半径排序(arr){

  设maxNum=arr[0];

  //找到最大的数字,用来确定最大的小数位数。

  arr.forEach(num={

  if(num maxNum){

  maxNum=num

  }

  });

  //有多少位数才能得到最大数?

  设maxDigitNum=0;

  while(maxNum 0){

  maxNum=math . floor(maxNum/10);

  maxDigitNum

  }

  //对每个十进制位上的数字进行排序

  for(设I=0;i maxDigitNumi ){

  假设桶=新数组(10)。填充(0)。map(()=[]);//初始化10个桶

  for(设k=0;k排列长度;k ){

  const bucket index=getDigitNum(arr[k],I);//获取当前小数点后的数字

  桶[桶指数]。push(arr[k]);//将数字排序到相应的桶中

  }

  //所有数字都放入桶中后,现在按照0-9的顺序从桶中取出数字。

  const RES=[];

  buckets.forEach(store={

  store.forEach(num={

  res.push(数字);//这里注意,先把存储在桶里的数字取出来,这样可以保持局部顺序。

  })

  });

  arr=res

  }

  返回arr

  /**

  找出数字的每个小数点上的数字。仅支持正整数。

  @param num整数

  @param digit数字,从0开始

  */

  函数getDigitNum(num,digit){

  返回Math.floor(num/Math.pow(10,数字)% 10)

  }

  }

算法复杂度

  【相关推荐:javascript视频教程,web前端】以上是JavaScript实现的十大排序算法的详细内容(图文详解)。更多请关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: