zoukankan      html  css  js  c++  java
  • js 常用排序整理

    排序:
      1. 内部排序:
        (1). 交换排序:
          1). 冒泡排序 稳定
            一次比较相邻两个元素的大小,顺序错误的,将其位置互换
            (从高位到低位 或者 从低位到高位)

    初始版: 

     1           var array = [6, 5, 3, 1, 8, 7, 2, 4],
     2         length = array.length,
     3         temp = '';
     4         for (var i=0; i<length-1; i++) {
     5             for (var j=0; j<length-i-1; j++) {
     6                 if (array[j]>array[j+1]) {
     7                     temp = array[j];
     8                     array[j] = array[j+1];
     9                     array[j+1] = temp;
    10                 }
    11             }
    12         }
    13         console.log(array)    

     改进版(定义标志变量记录每次最后一次交换的位置索引,此标志变量之后的元素都已交换完成,故再次循环的时候只进行到标记变量的位置比较即可)

     1 var array = [6, 5, 3, 1, 8, 7, 2, 4],
     2     temp = '',
     3     i = array.length - 1;
     4     while (i > 0) {
     5         let pos = 0;
     6         for (let j = 0; j < i; j++) {
     7             if (array[j] > array[j + 1]) {
     8                 pos = j;
     9                 let temp = array[j];
    10                 array[j] = array[j + 1];
    11                 array[j + 1] = temp;
    12             }
    13         }
    14         i = pos;
    15     }
    16     console.log(array)

    鸡尾酒(定向冒泡排序)(从高位到低位的同时也从低位到高位)

     1         var array = [6,5,3,1,8,7,2,4],
     2         length = array.length,
     3         temp = '',
     4         left = 0,
     5         right = length-1;
     6         while (left<right) {
     7             for (var i=0; i<right; i++) {
     8                 if (array[i]>array[i+1]) {
     9                     temp = array[i];
    10                     array[i] = array[i+1];
    11                     array[i+1] = temp;
    12                 }
    13             }
    14             right--;
    15             for (var i=right; i>left; i--) {
    16                 if (array[i]<array[i-1]) {
    17                     temp = array[i];
    18                     array[i] = array[i-1];
    19                     array[i-1] = temp;
    20                 }
    21             }
    22             left++;
    23         }
    24         console.log(array)

           2). 快速排序 不稳定
            1. 取数组中间索引(pivotIndex)
            2. 去数组中间位置元素(pivot = Number(array.splice(pivotIndex, 1)))
            3. 新建两个空数组left, right
            4. 循环跟数组中间元素比较,大的放right,小的放left
            5. 递归回调: 对left,right 分别递归回调形成有序的数组后
            6. 最后,将有序的left pivot right 三部分 concat 起来

     1 var array = [6,5,3,1,8,7,2,4];
     2 function quickSort(array) {
     3     if (array.length <= 1) {
     4         return array;
     5     }
     6     const pivotIndex = parseInt(array.length / 2);
     7     const pivot = Number(array.splice(pivotIndex, 1));
     8     const left = [];    const right = [];
     9     for (let i = 0; i < array.length; i++) {
    10         if (array[i] < pivot) {
    11             left.push(array[i]);
    12         } else {
    13             right.push(array[i]);
    14         }
    15     }
    16     return quickSort(left).concat([pivot], quickSort(right));
    17 };
    18 console.log(array)            

        (2). 插入排序:
          1). 直接插入排序 稳定
            1. 取无序序列的第一个最为有序序列
            2. 从第二个开始抓取,从有序序列的末尾开始向前找
            3. 如果 比较到的元素(有序序列中的元素)(array[j]) > 被比较的元素(要插入的元素)(key),则 将前者向后移动一个位置(array[j+1] = array[j])
            4. 如果 比较到的元素(有序序列中的元素)(array[j]) >= 被比较的元素(要插入的元素)(key),则 将后者放置前者的下一个位置处(array[j+1] = key)

     1         var array = [6,5,3,1,8,7,2,4];
     2         for (let i = 1; i < array.length; i++) {
     3             let key = array[i];
     4             let j = i - 1;
     5             while (j >= 0 && array[j] > key) {
     6                 array[j + 1] = array[j];
     7                 j--;
     8             }
     9             array[j + 1] = key;
    10         }
    11         console.log(array)

          2). 二分法插入排序
            1. 取无序序列第一个元素作为有序序列(即有序序列的起始)(有序序列:array[0]~array[i-1])
            2. 取下一个元素(array[i])作为被插入元素并做记录为 key
            3. 取有序序列的开始及结束位置的索引分别为 left 和 right
            4. 取有序序列的中间索引为 middle= Math.floor((left+right)/2)
            5. 将 middle 位置的元素 array[middle] 与 被插入元素 key 比较,
              如果 key > array[middle],便置 left = middle+1,
              反之 key > array[middle] ,则置 right = middle-1,
              直至 right < left 为止
              (此步骤为 二分查找 原理)
            6. 对从 left 到 key值元素所在位置索引 i-1 处之间的有序序列 array[left]~array[i-1] 与 key 两者之间采用 直接插入法 进行插入
            7. 重复以上步骤 2~6

     1         var array = [6,5,3,1,8,7,2,4];
     2         for (let i = 1; i < array.length; i++) {
     3             let key = array[i], left = 0, right = i - 1;
     4             //console.log(i+'++'+key);
     5             //console.log(left+'=='+right);
     6             while (left <= right) {
     7                 let middle = parseInt((left + right) / 2);
     8                 //console.log(left+'=='+middle+'=='+right)
     9                 if (key < array[middle]) {
    10                     right = middle - 1;
    11                 } else {
    12                     left = middle + 1;
    13                 }
    14                 //console.log(left+'=='+right)
    15             }
    16             //console.log(array)
    17             for (let j = i - 1; j >= left; j--) {
    18                 array[j + 1] = array[j];
    19             //console.log(array)
    20             }
    21             array[left] = key;
    22             //console.log(array)
    23         }
    24         console.log(array)

          3). 希尔排序 不稳定
            不太理解

     1         var arr=[49,38,65,97,76,13,27,49,55,4],
     2         len=arr.length;
     3         for(var fraction = Math.floor(len/2);fraction>0;fraction = Math.floor(fraction/2)){
     4             for(var i=fraction;i<len;i++){
     5                 for(var j=i-fraction;j>=0&&arr[j]>arr[fraction+j];j-=fraction){
     6                     var temp=arr[j];
     7                     arr[j]=arr[fraction+j];
     8                     arr[fraction+j]=temp;
     9                 }
    10             }
    11         }
    12         console.log(arr);


        (3). 选择排序:
          1). 简单选择排序 不稳定
            1. 取序列的第一个元素作为有序序列,并取该序列末尾索引位置为作参照,minIndex=0
            2. 从序列的第二个元素开始与 array[minIndex] 做比较,如果小就记该元素位置索引为 minIndex,
            3. 重复操作步骤2 直至再无更小元素为止,将此时的 minIndex 与有序序列的末尾元素互换
            (先从未排序序列中找出最小(大)元素,将该最小元素与序列的起始位置交换,至此 最小元素即到了有序元素的起始位置,
            然后 再从剩余的未排序序列中继续寻找最小(大)元素,依次与未排序序列中的起始位置互换,至此 次大的元素就依次放到了有序序列的末尾)

     1         var array = [6,5,3,1,8,7,2,4],
     2               length = array.length;
     3         for (let i = 0; i < length - 1; i++) {
     4             let minIndex = i;
     5             console.log(array[minIndex]);
     6             for (let j = i + 1; j < length; j++) {
     7                 if (array[j] < array[minIndex]) {
     8                     minIndex = j;
     9                 }
    10             }
    11             let temp = array[i];
    12             array[i] = array[minIndex];
    13             array[minIndex] = temp;
    14             console.log(array);
    15         }
    16         console.log(array)

          2). 堆排序 不稳定

        (4). 归并排序: 稳定
          1). 递归原理
            1. 利用递归将数组对半开分为 left,right 两个数组,直到每个拆分完的数组中只有一个元素为止,将每个数组视为有序数组
            2. 创建一个新的数组 newArray 来放排好序的元素
            3. 从每个数组的第一个元素开始拿来比较,往newArray里放,小的先放,大的后放
            注:步骤1 是递归进最里层,步骤3 是递归往外出,最后得到有序序列

     1             function mergeSort(array) {
     2             if (array.length < 2) {
     3                 return array;
     4             }
     5             const middle = parseInt(array.length / 2);
     6             const left = array.slice(0, middle);
     7             const right = array.slice(middle);
     8             return merge(mergeSort(left), mergeSort(right));
     9         }
    10         function merge(left, right) {
    11             const newArray = [];
    12             while (left.length && right.length) {
    13                 if (left[0] <= right[0]) {
    14                     newArray.push(left.shift());
    15                 } else {
    16                     newArray.push(right.shift());
    17                 }
    18             }
    19             while (left.length) {
    20                 newArray.push(left.shift());
    21             }
    22             while (right.length) {
    23                 newArray.push(right.shift());
    24             }
    25             return newArray;
    26         }

          2). 基数排序: 稳定
      2. 外部排序:
        (1). 计数排序 稳定
        (2). 桶排序 稳定

    http://www.cnblogs.com/eniac12/p/5329396.html

    http://www.cnblogs.com/eniac12/p/5332117.html

    http://www.jianshu.com/p/96f5c19e13df

  • 相关阅读:
    【BZOJ 3732】 Network
    【BJOI 2018】 求和
    【HDU 1005】 Number Sequence
    【HDU 3652】 B-numbers
    【SCOI 2007】 降雨量
    BZOJ2186 SDOI2008沙拉公主的困惑(数论)
    #38 游戏(线段树)
    BZOJ2339 HNOI2011卡农(动态规划+组合数学)
    BZOJ3107 CQOI2013二进制A+B(动态规划)
    BZOJ3083 遥远的国度(树链剖分+线段树)
  • 原文地址:https://www.cnblogs.com/s-qiu/p/6758480.html
Copyright © 2011-2022 走看看