js 十大排序算法:冒泡排序

排序算法说明:

(1)对于评述算法优劣术语的说明

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

内排序:所有排序操作都在内存中完成;
外排序:由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行;

时间复杂度: 一个算法执行所耗费的时间。
空间复杂度: 运行完一个程序所需内存的大小。

(2)排序算法图片总结:

  

 

1.冒泡排序:

解析:1.比较相邻的两个元素,如果前一个比后一个大,则交换位置。

   2.第一轮的时候最后一个元素应该是最大的一个。

   3.按照步骤一的方法进行相邻两个元素的比较,这个时候由于最后一个元素已经是最大的了,所以最后一个元素不用比较。

function sort(elements){
    for(var i=0;i<elements.length-1;i++){
        for(var j=0;j<elements.length-i-1;j++){
            if(elements[j] > elements[j+1]){
                var swap = elements[j];
                elements[j] = elements[j+1];
                elements[j+1] = swap;
            }
        }
    }
}
var elements = [3,1,5,7,2,4,9,6,10,8];
console.log('before:' + elements);
sort(elements);
console.log('after' + elements);

 

2.快速排序:

解析:快速排序是对冒泡排序的一种改进,第一趟排序时将数据分成两部分,一部分比另一部分的所有数据都要小。然后递归调用,在两边都实行快速排序。

 

function quickSort(elements){
    if(elements.length<=1){
        return elements;
    }
    var pivotIndex = Math.floor(elements.length / 2);
    var pivot = elements.splice(pivotIndex,1)[0];
    var left = [];
    var right = [];
    for(var i=0;i<elements.length;i++){
        if(elements[i]<pivot){
            left.push(elements[i]);
        } else{
            right.push(elements[i]);
        }
    }
    return quickSort(left).concat([pivot],quickSort(right));
}
var elements = [5,6,2,1,3,8,7,1.2,5.5,4.5];
document.write(quickSort(elements));

3.插入排序:

解析:

 (1) 从第一个元素开始,该元素可以认为已经被排序

 (2) 取出下一个元素,在已经排序的元素序列中从后向前扫描

 (3) 如果该元素(已排序)大于新元素,将该元素移到下一位置

 (4) 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置

 (5)将新元素插入到下一位置中

 (6) 重复步骤2

function sort(elements){
    //假设第0个元素是一个有序的数列,第1个以后的是无序的序列,
    // 所以从第1个元素开始将无序数列的元素插入到有序数列中
    for(var i=1;i<elements.length;i++){
        //升序
        if(elements[i] < elements[i-1]){
            //取出无序数列中的第i个作为被插入元素
            var guard = elements[i];
            //计主有序数列的最后一个位置,并且将有序数列位置扩大一个
            var j = i-1;
            elements[i] = elements[j];
            //比大小,找到被插入元素所在的位置
            while(j>=0 && guard < elements[j]){
                elements[j+1] = elements[j];
                j--;
            }
            elements[j+1] = guard;//插入
        }
    }
}
var elements = [5,9,3,6,7,4,1,8,2];
document.write('没调用之前:'+ elements);
document.write('<br/>');
sort(elements);
document.write('调用之后:'+elements);

2.二分查找:

解析:二分查找,也为折半查找。首先要找到一个中间值,通过与中间值比较,大的放又,小的放在左边。再在两边中寻找中间值,持续以上操作,直到找到所在位置为止。

(1)递归方法 

function binarySearch(data,dest,start,end){
    var end = end || data.length - 1,
        start = start || 0,
        m = Math.floor((start+end) / 2);
        if(data[m] == dest){
            return m;
        }
        if(dest < data[m]){
            return binarySearch(data,dest,0, m-1);
        }else{
            return binarySearch(data,dest, m+1,end);
        }
        return false;
}
var arr = [-34,1,3,4,5,8,34,45,65,87];
document.write(binarySearch(arr,4));

(2)非递归方法

function binarySearch(data,dest){
    var h = data.length -1,
        l = 0;
    while(l <= h){
        var m = Math.floor((h+l)/2);
        if(data[m] == dest){
            return m;
        }
        if(dest > data[m]){
            l = m + 1;
        }else{
            h = m - 1;
        }
    }
    return false;
}
var arr = [-34,1,3,4,5,8,34,45,65,87];
document.write(binarySearch(arr,4));//3

4.选择排序:

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

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

function selectionSort(arr){
    var len = arr.length;
    var minIndex,temp;
    console.time('选择排序耗时');
    for(var i=0;i<len-1;i++){
        minIndex = i;
        for(var j=i+1;j<len;j++){
            if(arr[j] < arr[minIndex]){//寻找最小的数
                minIndex = j;//将最小数的索引保存
            }
        }
        temp = arr[i];
        arr[i] = arr[minIndex];
        arr[minIndex] = temp;
    }
    console.timeEnd('选择排序耗时');
    return arr;
}
var arr = [3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(selectionSort(arr));//[2,3,4,5,15,19,26,27,36,44,46,47,48,50]

5.希尔排序:

解析:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序

function shellSort(arr){
    var len = arr.length,temp,gap = 1;
    console.time('希尔排序耗时:');
    while(gap < len / 5){//动态定义间隔序列
        gap = gap * 5 + 1;
    }
    for(gap;gap > 0;gap = Math.floor(gap / 5)){
        for(var i=gap; i <len;i++){
            temp = arr[i];
            for(var j=i-gap;j>=0 && arr[j] > temp; j -= gap){
                arr[j + gap] = arr[j];
            }
            arr[j + gap] = temp;
        }
    }
    console.timeEnd('希尔排序耗时:');
    return arr;
}
var arr = [3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
document.write(shellSort(arr));//[2,3,4,5,15,19,26,27,36,38,44,46,47,48,50]

6.归并排序:

解析:归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

function mergeSort(arr){
    var len = arr.length;
    if(len < 2){
        return arr;
    }
    var middle = Math.floor(len / 2),
        left = arr.slice(0,middle),
        right = arr.slice(middle);
    return merge(mergeSort(left),mergeSort(right));
}
function merge(left,right){
    var result = [];
    console.time('归并排序耗时');
    while(left.length && right.length){
        if(left[0] <= right[0]){
            result.push(left.shift());
        }else{
            result.push(right.shift());
        }
    }
    while(left.length){
        result.push(left.shift());
    }
    while(right.length){
        result.push(right.shift());
    }
    console.timeEnd('归并排序耗时');
    return result;
}
var arr = [3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
document.write(mergeSort(arr));//[2,3,4,5,15,19,26,27,36,38,44,46,47,48,50]

  

7.堆排序:

解析:堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是

  小于(或者大于)它的父节点。

//堆排序
function heapSort(array){
    console.time('堆排序耗时');
    if(Object.prototype.toString.call(array).slice(8,-1)=== 'Array'){
        var heapSize = array.length,temp;//建堆
        for(var i=Math.floor(heapSize/2) - 1;i>=0;i++){
            heapify(array,i,heapSize);
        }
        for(var j = heapSize - 1; j>= 1;j--){
            temp = array[0];
            array[0] = array[j];
            array[j] = temp;
            heapify(array,0, --heapSize);
        }
        console.timeEnd('堆排序耗时');
        return array;
    }else{
        return 'array is not an Array!';
    }
}

function heapify(arr,x,len){
    if(Object.prototype.toString.call(arr).slice(8,-1)==='Array'&&typeof x === 'number'){
        var l = 2*x+1,
            r = 2*x+2,
            largest = x,
            temp;
            if(l < len && arr[l] > arr[largest]){
                largest = l;
            }
            if(r < len && arr[r]> arr[largest]){
                largest = r;
            }
            if(largest != x){
                temp = arr[x];
                arr[x] = arr[largest];
                arr[largest] = temp;
                heapify(arr,largest,len);
            }
    }else{
        return 'arr is not an Array or x is not a number!';
    }
}
var arr = [91,60,96,13,35,65,46,65,10,30,20,31,77,81,22];
document.write(heapSort(arr));//[2,3,4,5,15,19,26,27,36,38,44,46,47,48,50]

8.计数排序:

 解析:计数排序使用一个额外的数组C,其中第i个元素是待排序数组A中值等于i的元素的个数。然后根据数组C来将A中的元素排到正确的位置。它只能对整数进行排序。

function countingSort(array){
    var len = array.length,B = [], C =[],
        min = max = array[0];
    console.time('计数排序耗时');
    for(var i=0; i<len; i++){
        min = max<=array[i] ? min: array[i];
        max = max>=array[i] ? max: array[i];
        C[array[i]] = C[array[i]] ? C[array[i]] + 1 : 1;
    }
    for(var j=min; j < max; j++){
        C[j+1] = (C[j + 1] || 0) + (C[j] || 0);
    }
    for(var k = len - 1; k >=0 ;k--){
        B[C[array[k]] -1] = array[k];
        C[array[k]]--;
    }
    console.timeEnd('技术排序耗时');
    return B;
}
var arr = [2,2,3,8,7,1,2,2,2,7,3,9,8,2,1,4,2,4,6,9,2];
document.write(countingSort(arr));//[1,1,2,2,2,2,2,2,2,2,3,3,4,4,6,7,7,8,8,9,9]

9.桶排序:

解析:假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排

  

10.基数排序:

解析:基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优

  先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。基数排序基于分别排序,分别收集,所以是稳定的。

  

基数排序 vs 计数排序 vs 桶排序

这三种排序算法都利用了桶的概念,但对桶的使用方法上有明显差异:

基数排序:根据键值的每位数字来分配桶 计数排序:每个桶只存储单一键值 桶排序:每个桶存储一定范围的数值

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值