首页 > 技术文章 > [算法]排序

binking338 2013-11-24 17:59 原文

基础排序算法大致分为三大类,选择排序、插入排序、交换排序。下面是三类排序算法的一些javascript实现整理。

选择排序

简单选择排序

// 选择排序
function selection_sort(arr)
{
    var n = arr.length;
    var i, j, min, t;
    for( i =0; i < n -1; i ++)
    {
        min = i; 
        // 查找最小值
        for( j = i +1; j < n; j ++)
            if( arr[min] > arr[j])min = j; 
        // 交换
        if( min != i)
        {
            t = arr[min];
            arr[min] = arr[i];
            arr[i] = t;
        }
    }
    return arr;
}

堆排序

// 堆排序(选择排序一种)
function heap_sort(arr)
{  
    // arr是待调整的堆数组,i是待调整的数组元素的位置,n是数组的长度
    // 本函数功能:根据数组arr构建大根堆(每一个分支从根到叶子都是递减,根最大)
    function heap_adjust(arr, i, n)
    {
        var child;
        var t;
        for (t = arr[i]; 2 * i + 1 < n; i = child)
        {
            // 子结点的位置=2*(父结点位置)+ 1
            child = 2 * i + 1;
            // 得到子结点中较大的结点
            if ( child < n-1 && arr[child + 1] > arr[child])
                ++child;
            // 如果较大的子结点大于父结点那么把较大的子结点往上移动,替换它的父结点,下个循环比较替换后的分支
            if (t < arr[child])
            {
                arr[i] = arr[child];
                arr[child]= t;
            }
            else
            // 否则退出循环
                 break;
        }
    }
    var n = arr.length;
    var t;
    // n/2-1是倒数第一个非叶节点
    // 调整数的每一个分支使得每一个分支从根到叶子都是大到小排列
    for (var i = n / 2 - 1; i >= 0; --i)
        heap_adjust(arr, i, n);
    // 从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
    for (var i = n - 1; i > 0; --i)
    {
        // 把第一个元素和当前的最后一个元素交换,
        // 保证当前的最后一个位置的元素都是在现在的这个序列之中最大的
        t = arr[i];
        arr[i] = arr[0];
        arr[0] = t;
        
        // 取出二叉树的第二层中较大数上升至根节点,根节点下沉至较大数分支,更新该分支,将值下沉至合适位置。
        heap_adjust(arr, 0, i);
    }
    return arr;
}

插入排序

直接插入排序

// 直接插入排序算法
function insertion_sort(arr) 
{
    var n = arr.length;
    var t, j;
    // 循环从第二个数组元素开始,arr[0]作为最初已排序部分
    for(var i=1;i<n;i++) 
    {
        // 挖出arr[i] (t标记为未排序第一个元素)
        t=arr[i];
        j=i-1;
        // 将t与已排序元素从大到小比较,寻找t应插入的位置
        while (j>=0 && arr[j]>t)
        { 
            arr[j+1]=arr[j];  
            j--; 
        } 
        arr[j+1]=t; 
    } 
    return arr;
} 

希尔排序

// 希尔排序(插入排序一种)
function shell_sort(arr)
{
    var n = arr.length;
    var fraction,i,j,t;
    // 取数组1/2作为初始增量
    for(fraction=Math.floor(n/2); fraction>0; fraction=Math.floor(fraction/2)) {
        for(i = fraction; i<n; i++ ) {
            for(j = i-fraction; j>=0 && arr[j]>arr[fraction+j]; j-=fraction ) {
                t = arr[j];
                arr[j] = arr[fraction+j];
                arr[fraction+j] = t;
            }
        }
    }
    return arr;
}

合并排序

// 合并排序(本人认为也是插入排序一种)
function merge_sort(arr, s, e, b){
    s = s || 0; 
    e = e || arr.length - 1;
    b = b || new Array(arr.length);
    if (s >= e)
        return;
    var m = (s + e) >> 1;
    merge_sort(arr, s, m, b);
    merge_sort(arr, m + 1, e, b);
    for (var i = s, j = s, k = m + 1; i <= e; ++i)
        b[i] = arr[(k > e || j <= m && arr[j] < arr[k]) ? j++ : k++];
    for (var i = s; i <= e; ++i)
        arr[i] = b[i];
}

交换排序

冒泡排序

// 冒泡排序(交换排序一种)
function bubble_sort(arr){
    var t,i,j;
    // 一共比较n-1趟
    for(i=0;i<arr.length-1;i++){
        // 对当前无序区arr[i..n]自左向右扫描
        for(j=0;j<arr.length-i-1;j++){
                if(arr[j]>arr[j+1]){
                    //交换
                    t=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=t;
                }
            }
        }
    return arr;
}

快速排序

// 递归实现快速排序(交换排序一种)
function quick_sort(arr, l, r)
{
    var i,j,x;
    l = l || 0;
    r = r || arr.length-1;
    if (l < r)
    {
        i = l, j = r, x = arr[l];
        while (i < j)
        {
            // 从右向左找第一个小于x的数
            while(i < j && arr[j] >= x) 
                j--; 
            if(i < j)
                arr[i++] = arr[j];
            // 从左向右找第一个大于等于x的数
            while(i < j && arr[i] < x) 
                i++; 
            if(i < j)
                arr[j--] = arr[i];
        }
        arr[i] = x;
        quick_sort(arr, l, i - 1); // 递归调用
        quick_sort(arr, i + 1, r);
    }
    return arr;
}
// 栈式实现快速排序(交换排序一种)
function stack_quick_sort(arr) {
    var stack = [0, arr.length - 1];
    var i,index,e,t;
    while (stack.length > 0){
        e = stack.pop(), s = stack.pop();  
        if (s >= e)
            continue;
        t = arr[(s + e) >> 1];
        arr[(s + e) >> 1] = arr[e];
        arr[e] = t;
        index = s - 1;
        for (i = s; i <= e; ++i){
            if (arr[i] <= arr[e]){
                ++index;
                t = arr[i];
                arr[i] = arr[index];
                arr[index] = t;
            }
        }
        stack.push(s, index - 1, index + 1, e);
    }
    return arr;
}

推荐阅读