排序(JavaScript)----基本排序(冒泡,选择,插入,哈希,快速)

 

1.冒泡排序

img

  • 对未排序的各个元素从头到尾依次比较相邻两个元素的大小关系

  • 如果左边高,则交换两个元素的位置

  • 然后右移一格,比较下面的两个

  • 当移动到最右端(未排序的最右端) ,那么最大值就应该在这,那么这个最右端的就是已排序的

  • 然后从未排序的中继续寻找

 

  • 关于最外层循环的个数个计算:

  • arr.length个数,且最后一个不要排,所以要排arr.length-1

  • 未排序的最右端的计算:

  • 第一次:i=0 最大值放在arr.length-1上 计算arr.length-1-0

  • 第二次:i=0 最大值放在arr.length-2上 计算arr.length-1-1

  • ...

  • 总结为:arr.length-1-i */

function bubble_sort (arr) {
  for (let i = 0; i < arr.length - 1; i++) {
    for (let j = 0; j < arr.length - 1 - i; j++) {
      if (arr[j] > arr[j + 1]) {
        let flag = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = flag;
      }
    }
  }
  return arr
}
let result = bubble_sort([2, 1, 62, 4, 3, 7, 5, 88, 65, 0]);
console.log(result);

2.选择排序

img

function selectioin_sort (arr) {
  for (let i = 0; i < arr.length - 1; i++) {
    //不需要频繁交换,每趟都检测,是否应该换位置,如果要换位置,就把需要换的位置记录下来
    let recordIndex = i;
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[i] > arr[j]) {
        recordIndex = j;
      }
    }
    // 将记录下来的位置和i比较,如果不一致,就说明应该交换
    if (recordIndex != i) {
      let temp = arr[i];
      arr[i] = arr[recordIndex];
      arr[recordIndex] = temp;
    }
  }
  return arr;
}
let result = selectioin_sort([2, 1, 62, 4, 3, 7, 5, 88, 65, 0, -1, 33]);
console.log(result);

3.直接插入排序

排序(2):直接插入排序

 

思路(从小到大):

首先第一次的时候,默认第一位是已经排好序的

然后从第二个开始(前面是已排序的,后面是未排序的 ,而且每次都要用一个变量temp来记录这个未排序中的第一个数),与前面的已排序的进行比较(从已排序的最后一个开始比较 ,用j记录),如果比第二个大(arr[j] > temp),则向后移动一格(arr[j+1] = arr[j]),然后j--,再比较,直到最后找到一个小于temp,就停止。然后交换(arr[j+1] = temp

接着取下一组未排序中的第一个值,重复第二步,直到最后一个,就完成排序。

 

 

临界条件:temp比第一个(下标值为0)还小,那么继续j--此时下标值为-1) , 此时应该停止,这就说明,当j>=0的时候是不停止的

function inser_sort (arr) {
  for (let i = 1; i < arr.length; i++) {
    let temp = arr[i];
    let j = i - 1;//j在for循环外面,保证在下面可以用到
    for (j; j >= 0 && arr[j] > temp; j--) {
      arr[j + 1] = arr[j];
    }
    //因为每次比较的时候都是arr[j] > temp , 当遇到arr[j] <= temp的时候,已经是不需要移动了,所以要+1插入到后面的一个空位
    arr[j + 1] = temp;
  }
  return arr;
}
​
let result = inser_sort([2, 1, 62, 4, 3, 7, 5, 88, 65, 0]);
console.log(result);

 

4.希尔排序

希尔排序(Shell's Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法

该方法实质上是一种分组插入方法

比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换。D.L.shell于1959年在以他名字命名的排序算法中实现了这一思想。算法先将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。

一般的初次取序列的一半为增量,以后每次减半,直到增量为1。 ----------------来自百度

这个版本是在找资料过程中发现的一个比较好的,思路清晰,比其他的读起来更加容易一点

希尔原文

function shell_sort (arr) {
  let length = arr.length;
  for (let gap = parseInt(length / 2); gap > 0; gap = parseInt(gap / 2)) {
    for (let i = gap; i < length; i++) {
​
      insert_sort(arr, i, gap);
    }
  }
  return arr;
}
​
function insert_sort (arr, index, gap) {
  // 为什么这里不能用j=index,然后用index来记录需要插入的值,因为index虽然是不该变得,但是如果平移之后,index里所对应的值就改变了
  let insert = arr[index];
  let j;
  for (j = index - gap; j >= 0 && arr[j] > insert; j -= gap) {
​
    arr[j + gap] = arr[j];
  }
  arr[j + gap] = insert;
​
}
let arr = [2, 1, 62, 4, 3, 7, 5, 88, 65, 0]
let result = shell_sort(arr);
​
console.log(arr);

5.快速排序

注:从小到大

此代码来自b站coderwhy的数据结构

 

基准选择:

 

left , right , mid = parseInt((left + right) / 2)(将其转化为整数) , 然后将这三个位置上的数,从小到大排列,mid就是基准值

为了不让基准值到最后或者是最前面 , 将mid与length-1位置上的数交换,最后将基准值返回出去。

// 基准判定的函数
function pivotFunc (arr, left, right) {
  let mid = parseInt((right + left) / 2);
​
  if (arr[left] > arr[mid]) {
    [arr[left], arr[mid]] = [arr[mid], arr[left]];
  }
​
​
  if (arr[left] > arr[right]) {
    [arr[left], arr[right]] = [arr[right], arr[left]];
  }
​
  // 前两个if是确定第一位是最小的
  // 下面的if只要做两个数大小的判断
  if (arr[mid] > arr[right]) {
    [arr[mid], arr[right]] = [arr[right], arr[mid]]
  }
​
  // 让基准数再放倒数第二个
  [arr[mid], arr[right - 1]] = [arr[right - 1], arr[mid]]
​
  return arr[right - 1];
}

进行快速排序

快速排序大多数使用递归,递归的终止条件是,left>=right . 当left >=right的时候,说明到最后,每组只有一个数据。

首先要明白的一点,pivot的左边是小于pivot的,右边是大于等于pivot的

然后,先获取 let pivot = pivotFunc(arr, left, right); ,记住现在的pivot已经被记录下来了

用i=left来记录左边的位置

用j=right-1来记录右边的位置(j=right-1的原因是,right是大于基准值的,right-1是基准值得位置,)

然后从i开始,如果arr[i] < pivot,就说明没有大于基准值,所以i++,当arr[i]>=pivot的时候,需要暂停i这边的,然后从j往前找有没有小于pivot的,如果有,就将他们两个交换,如果没有,j--

 

找到j<pivot就交换arr[i]和arr[j]

然后接着重复以上步骤,直到i<j不成立。

function quick_sort (arr, left, right) {
  if (left >= right) return;
  let pivot = pivotFunc(arr, left, right);
  let i = left;
  let j = right - 1;
  while (true) {
    while (i < j && arr[i] < pivot) i++;
    while (i < j && arr[j] > pivot) j--;
    if (i < j) {
      [arr[i], arr[j]] = [arr[j], arr[i]]
    } else {
      break;
    }
  }
  [arr[i], pivot] = [pivot, arr[i]];
  quick_sort(arr, left, i - 1);
  quick_sort(arr, i + 1, right);
  return arr;
​
}

 ​

全部代码:

// 基准判定的函数
function pivotFunc (arr, left, right) {
  let mid = parseInt((right + left) / 2);
​
  if (arr[left] > arr[mid]) {
    [arr[left], arr[mid]] = [arr[mid], arr[left]];
  }
​
​
  if (arr[left] > arr[right]) {
    [arr[left], arr[right]] = [arr[right], arr[left]];
  }
​
  // 前两个if是确定第一位是最小的
  // 下面的if只要做两个数大小的判断
  if (arr[mid] > arr[right]) {
    [arr[mid], arr[right]] = [arr[right], arr[mid]]
  }
​
  // 让基准数再放倒数第二个
  [arr[mid], arr[right - 1]] = [arr[right - 1], arr[mid]]
​
  return arr[right - 1];
}
​
function quick_sort (arr, left, right) {
  if (left >= right) return;
  let pivot = pivotFunc(arr, left, right);
  let i = left;
  let j = right - 1;
  while (true) {
    while (i < j && arr[i] < pivot) i++;
    while (i < j && arr[j] > pivot) j--;
    if (i < j) {
      [arr[i], arr[j]] = [arr[j], arr[i]]
    } else {
      break;
    }
  }
  [arr[i], pivot] = [pivot, arr[i]];
  quick_sort(arr, left, i - 1);
  quick_sort(arr, i + 1, right);
  return arr;
​
}
let arr = [2, 1, 62, 4, 3, 7, 5, 88, 65, 0];
console.log(arr);
let result = quick_sort(arr, 0, arr.length - 1);
console.log(result);

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值