js排序常用算法

一、冒泡排序

1、基本思想:

通过相邻元素的比较和交换,使得每一趟循环都能找到未有序数组的最大值或最小值

2、 冒泡排序代码

function bubblingSort(){
    //外循环,对被排序的数组进行遍历,轮数为数组的长度
	for (let i = 0; i < arr.length - 1; i++) {
        // 内循环 负责每轮交换的次数,循环比较相邻元素 
        for (let j = 0; j < arr.length - i - 1; j++) {
            //如果前一个元素大于后一个元素的话,就交换两个元素的位置,最后是以从大到小的顺序输出
            if (arr[j] > arr[j + 1]) {
                let temp = arr[j]
                arr[j] = arr[j + 1]
                arr[j + 1] = temp
            }
        }
	}
	return arr
}
let arr = [4,1,6,3,5,2]
console.log(bubblingSort(arr))   //  [1, 2, 3, 4, 5, 6]

拆分理解(从小到大排序):

  1. 那么4先和1比较,4大就与1交换位置;
  2. 4再和6比较 4小就不交换;
  3. 然后6就和3比较,6大交换位置;
  4. 直到最后一个比2大,那么6放在了数组的最后,下一次比较的数组变为arr=[5,8,4,7,3,2,9];
  5. 这样继续循环直到完成从小到大排序;
  6. 得到排序后的数组

二、选择排序

1、基本思想:

依次找到剩余元素的最小值或者最大值,放置在末尾或者开头

2、选择排序代码

function selectionSort() {
  // 循环遍历整个数组
  for (let i = 0; i < arr.length; i++) {
    // 假设当前索引的数字最小
    let minIndex = i;
    // 在后面的数中寻找更小的数
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[j] < arr[minIndex]) {
        // 如果找到更小的数,记录它的索引
        minIndex = j;
      }
    }
    // 如果循环后的索引不是之前假设的值,说明假设的值不是最小值,就交换它们
    if (i !== minIndex) {
      [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
    }
  }
  // 返回排序后的数组
  return arr;
}

let arr = [4,1,6,3,5,2];
const sortedArr = selectionSort(arr);   //  [1, 2, 3, 4, 5, 6]

拆分理解(从小到大排序):

  1. 首先循环遍历整个数组;
  2. 在每一次循环中,预设最小数的索引为当前循环的索引;
  3. 在后面的数中寻找更小的数,如果找到更小的数,记录它的索引;
  4. 如果当前循环的索引不是最小数的索引,交换它们;
  5. 重复步骤以上步骤,直到遍历完整个数组;
  6. 返回排序后的数组

三、插入排序

1、基本思想:

以第一个元素为有序数组,其后的元素通过再这个已有序的数组中找到合适的元素并插入

2、插入排序代码

function insertionSort(arr){
  // 对于数组的每一个元素,从它开始到0位置,比较该元素和前一个元素的大小
  for (let i = 1; i < arr.length; i++) {
    let current = arr[i];
    let j = i - 1;
    // 如果该元素小于前一个元素,那么前一个元素向后移动,并继续向前比较
    while (j >= 0 && arr[j] > current) {
      arr[j + 1] = arr[j];
      j--;
    }
    // 如果该元素大于前一个元素,那么它将放到合适的位置
    arr[j + 1] = current;
  }
  // 返回排序后的数组
  return arr;
}

const arr = [4,1,6,3,5,2];
const sortedArr = insertionSort(arr);   // [1, 2, 3, 4, 5, 6]

拆分理解:

  1. 首先,假设数组的第一个元素已经排好序了,因为它只有一个元素,所以可以认为是有序的。
  2. 然后,从第二个元素开始,不断与前面的有序数组元素进行比较。
  3. 如果当前元素小于前面的有序数组元素,则把当前元素插入到前面的合适位置。
  4. 否则,继续与前面的有序数组元素进行比较。
  5. 以此类推,直到整个数组都有序。
  6. 循环步骤2~5,直到最后一个元素。
  7. 完成排序

四、 快速排序

1、基本思想:

通过选取一个基准值,将待排序数组划分为左右两个子序列,其中左侧序列所有元素均小于基准值,右侧序列所有元素均大于基准值。之后对左右子序列递归进行快排操作,最终将整个序列排好序

2、排序的流程

快速排序的思路可以分解成以下几个步骤:

1、首先,我们需要选择一个基准元素,通常选择第一个或最后一个元素作为基准元素。
2、然后,我们定义两个指针 i 和 j,分别指向数组的左右两端。
3、接下来,我们从右侧开始,向左移动 j 指针,直到找到一个小于或等于基准元素的值。
4、然后,我们从左侧开始,向右移动 i 指针,直到找到一个大于或等于基准元素的值。
5、如果 i 指针小于或等于 j 指针,交换 i 和 j 指针所指向的元素。
6、重复步骤 3-5,直到 i 指针大于 j 指针,这时,我们将基准元素与 j 指针所指向的元素交换位置,将基准元素放到中间位置。
7、接着,我们将数组分为两部分,左侧部分包含小于或等于基准元素的元素,右侧部分包含大于基准元素的元素。
8、然后,对左右两部分分别进行递归调用快速排序,直到左右两部分只剩下一个元素。
9、最终,整个数组就变得有序了。

3、快速排序代码

function quickSort(arr) {
    if (arr.length <= 1) {
        return arr;
    }

    const pivotIndex = Math.floor(arr.length / 2);
    const pivot = arr[pivotIndex];
    const left = [];
    const right = [];

    for (let i = 0; i < arr.length; i++) {
        if (i === pivotIndex) {
            continue;
        }

        const currentItem = arr[i];

        if (currentItem < pivot) {
            left.push(currentItem);
        } else {
            right.push(currentItem);
        }
    }

    return [...quickSort(left), pivot, ...quickSort(right)];
}


// 测试数据
const arr = [4,1,6,3,5,2];
// 调用插入排序函数
const sortedArr = quickSort(arr);   //  [1, 2, 3, 4, 5, 6]

4、代码执行的过程

  1. 在数组中选择一个元素作为基准元素(通常是数组的第一个元素)
  2. 将小于等于基准元素的元素移到数组的左边,大于基准元素的元素移到数组的右边
  3. 递归地对左半部分数组和右半部分数组进行快速排序

五、归并排序

1、基本思想:

先将待排序数组递归地拆分成两个子数组,然后对每个子数组进行排序,最后将两个有序子数组合并成一个有序数组。

2、归并排序的流程

归并排序是一种基于分治思想的排序算法,其基本思路可以分为三个步骤:

步骤一:分解(Divide):归并排序使用递归算法来实现分解过程,具体实现中可以分为以下几个步骤:

如果待排序数组长度为1,认为这个数组已经有序,直接返回;
将待排序数组分成两个长度相等的子数组,分别对这两个子数组进行递归排序;
将两个排好序的子数组合并成一个有序数组,返回这个有序数组。

步骤二:合并(Merge):合并过程中,需要比较每个子数组的元素并将它们有序地合并成一个新的数组:
可以使用两个指针 i 和 j 分别指向两个子数组的开头,比较它们的元素大小,并将小的元素插入到新的有序数组中。
如果其中一个子数组已经遍历完,就将另一个子数组的剩余部分直接插入到新的有序数组中。
最后返回这个有序数组。

步骤三:归并排序的递归终止条件:

归并排序使用递归算法来实现分解过程,当子数组的长度为1时,认为这个子数组已经有序,递归结束。总体来看,归并排序的基本思路是分治法,分成子问题分别解决,然后将子问题的解合并成整体的解。

3、归并排序代码

function mergeSort(arr) {
    // 计算数组长度
    const n = arr.length;
    // 如果数组长度小于等于1,则直接返回该数组
    if (n <= 1) {
        return arr;
    }
    // 计算中间位置
    const middle = Math.floor(n / 2);
    // 对左边的数组进行归并排序
    const left = mergeSort(arr.slice(0, middle));
    // 对右边的数组进行归并排序
    const right = mergeSort(arr.slice(middle));
    // 合并两个排好序的数组
    return merge(left, right);
}

// 定义函数merge,参数是两个排好序的数组left和right
function merge(left, right) {
    // 定义指针变量,分别指向两个数组的开头
    let i = 0, j = 0;
    // 定义一个空数组,用来存放合并后的数组
    const result = [];
    // 比较两个数组的第一个元素,将较小的放入result数组
    while (i < left.length && j < right.length) {
        if (left[i] < right[j]) {
            result.push(left[i++]);
        } else {
            result.push(right[j++]);
        }
    }
    // 将没有比较完的剩余元素放入result数组
    while (i < left.length) {
        result.push(left[i++]);
    }
    while (j < right.length) {
        result.push(right[j++]);
    }
    // 返回合并后的数组
    return result;
}


// 测试数据
const testArr = [4,1,6,3,5,2];
// 调用插入排序函数
const sortedArr = mergeSort(testArr);  //  [1, 2, 3, 4, 5, 6]

4、代码执行的过程

  1. mergeSort 函数实现归并排序的递归调用,在该函数内,如果数组的长度小于等于1,直接返回该数组。
  2. 如果数组的长度大于1,那么执行以下代码:
    先计算数组的中点,并将数组分为左右两半。
    递归调用左边和右边的数组,最终得到两个有序的数组。
  3. merge 函数实现将两个有序的数组合并为一个有序的数组
  • 16
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值