数据结构——排序算法 选择排序 插入排序 希尔排序 归并排序 快速排序

排序算法命题

  • 没有任何基于比较的算法能够保证使用少于lg(N!)~NlgN次比较长度为N的数组排序。

排序算法模板

class Sort {
  less (v, w) {//比较大小,v比w小返回true。
    let re = (v-w < 0);
    return re;
  }
  exch (arr, i, j) {//交换
    let temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
  }
  show (arr) {//打印
    for (let i = 0; i < arr.length; i++) {
      console.log(arr[i]);
    }
  }
  isSorted (arr) { //是否排序完成。
    for (let i = 0; i < arr.length; i++){
      if (this.less(arr[i] ,arr[i-1])) return false;
    }
    return true;
  }
}
Sort.prototype.sort=sort;

选择排序

按顺序选出,最小,次小到最大。
时间复杂度O(n^2),不需要额外空间

function sort (arr) {
  for (let i = 0; i < arr.length; i++){
    let min = i;
    for (let j = i+1; j < arr.length; j++) {
      if (this.less(arr[j], arr[min])) {
        min=j;
      }
    }   
    this.exch(arr, i, min);
  }
  return arr;
}

插入排序

插入排序所需的时间取决于输入中元素的初始顺序。有序数组比无序数组快的多。
ave:比较和交换各N^2 /4次。
bad:比较与交换各N^2 /2次
best : 比较N-1,交换0次。

function sort (arr) {
  for (let i = 1; i < arr.length; i++){
    for (let j = i; j >= 0 && this.less(arr[j], arr[j-1]); j--){
      this.exch(arr, j, j-1);
    }
  }
  return arr;
}

希尔排序

思想: 一个数组中任意间隔为h的元素都是有序的。
性能不能确定

//希尔排序
//使用希尔增量
function sort (arr) {
  let h = Math.floor(arr.length / 2);
  while (h >= 1){
    for(let i = h; i < arr.length; i++){
      for(let j = i; j >= 0 && this.less(arr[j], arr[j-h]); j = j-h){
        this.exch(arr, j, j-h);
      }
    }
    h=Math.floor(h / 2);
  }
  return arr;
}

归并排序

function merge (arr, lo, mid, hi) {
    let i = lo;
    let j = mid+1;
    let aux=arr.slice();
    for (let k = lo;k <= hi; k++){
        if (i > mid) arr[k] = aux[j++];
        else if (j > hi) arr[k] = aux[i++];
        else if (aux[i] > aux[j]) arr[k] = aux[j++];
        else arr[k] = aux[i++];
    }
    return arr;
}

自顶向下的归并排序.

  • 对于长度为N的任意数组,自顶向下的归并排序需要N/2*lgN至NlgN次比较
  • 主要缺点数组所使用的额外空间和N的大小成正比。
function sort (arr, lo, hi) {
    if (hi <= lo) return;
    let mid = Math.floor ((lo + hi) / 2);
    sort(arr, lo, mid);
    sort(arr, mid+1, hi);
    merge(arr, lo, mid, hi);
    return arr;
}

自低向上的归并排序。

function sort (arr) {
    let N = arr.length;
    for (let sz = 1; sz < N; sz+=sz) {
        for (let i = 0; i < N; i+=2*sz) {
            merge(arr, i, i+sz-1, Math.min(i+2*sz-1, N));
        }
    }
    return arr;
}
  • 差别
    当数组长度为2的幂时, 自顶向下和自底向上的归并排序的比较次数和数组访问次数相同,顺序不同。其他时候,两种方法的比较和数组访问的次序都有不同。

  • 适用
    自底向上的归并排序比较适合用链表组织的数据。只需要重新组织链表的链接就能实现原地排序。

快速排序

长度为N的无重复数组排序,快速排序平均需要2NlgN次比较
快速排序最多需要N^2/2次比较

function sort (arr, lo, hi){
    let exch=this.exch;
    if(lo >= hi){return arr};
    let mid = partition (arr, lo, hi);
    this.sort(arr, lo, mid-1);
    this.sort(arr, mid+1, hi);
    function partition (arr, lo, hi) {
        let i = lo+1;
        let j = hi;
        while (i <= j) {
            while (arr[lo] > arr[i] && i <= hi) { i++ ;}
            while (arr[lo] <= arr[j] && j >= i) { j--;}
            if(i >= j){ break };
            exch(arr, i, j);
        }
        exch(arr, lo, j);
        return j;
    }
    return arr;
}

三向切分的快速排序
* a[i] 小于v,将a[lt]和a[i]交换,lt++,i++;
* a[i] 大于v,将a[gt]和a[i]交换,gt–
* a[i] 等于v , i++;
参考图示

function sort (arr, lo, hi){
    console.log(arr, lo, hi);
    if(hi <= lo){
        return arr;
    }
    let gt = hi;
    let i = lo;
    let lt = lo;
    let v = arr [lo];
    while (gt >= i) {
        console.log(arr,i,lt,gt);
        if (arr[i] < v) {
            this.exch(arr, lt, i);
            i++;
            lt++;
        }else if (arr[i] > v) {
            this.exch(arr, i, gt);
            gt--;
        }else if (arr[i] === v){
            i++;
        }
    }
    this.sort(arr, lo, lt-1);;
    this.sort(arr, gt+1, hi);
    return arr;
}

猜你喜欢

转载自blog.csdn.net/lay136362687/article/details/81234474