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的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。