javaScript数据结构:排序算法的实现

本文详细介绍了JavaScript中四种经典排序算法:冒泡排序、选择排序、插入排序和归并排序,包括它们的实现原理、时间复杂度及示例代码。通过实例演示,帮助理解排序算法在实际开发中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

javaScript数据结构:排序算法的实现

1.冒泡排序

bubbleSort : O(n^2)

原理:
从左到右,相邻元素进行比较,如果前一个元素值大于后一个元素值(正序),则交换,这样一轮下
来,将最大的数在最右边冒泡出来。这样一轮一轮下来,最后实现从小到大排序。

Array.prototype.bubbleSort = function() {
  //console.log(this);//这里的this就是自己的数组,比如这里输出的是[ 5, 4, 3, 2, 1 ]
  for(let i = 0; i<this.length - 1; i+=1) {
    for(let j=0; j<this.length-1-i;j+=1){
      if(this[j] > this[j+1]) {
        const temp = this[j];
        this[j] = this[j+1];
        this[j+1] = temp;
      }
    }
  }
}

const arr = [5,4,8,2,10]
arr.bubbleSort();
console.log(arr);//[ 2, 4, 5, 8, 10 ]

//bubbleSort :O(n^2)

2.选择排序

selectionSort: O(n^2)
把第一个没有排序过的元素设置为最小值,
从前往后遍历每个没有排序过的元素,
如果元素 < 现在的最小值
将此元素设置成为新的最小值,
将最小值和第一个没有排序过的位置交换。

这样下来,每一趟排序都会找到一个最小值,将它放在队列的前面。

Array.prototype.selectionSort = function() {
  //console.log(this);//这里的this就是自己的数组,比如这里输出的是[ 5, 4, 3, 2, 1 ]
  for(let i = 0; i< this.length - 1;i += 1) {
    
    //在每一轮循环里,将第一个未排序的数字当做最小值
    let indexMin = i;
    for(let j = i; j < this.length; j += 1) {
      if(this[j] < this[indexMin]) {
        indexMin = j;
      }
    }
    //上面的for循环结束后,此时已经得到了真正最小值的下标为indexMin
    //如果最小值不是每次排序的第一个数,那么就交换
    if(indexMin !== i) {
      const temp = this[i];
      this[i] = this[indexMin];
      this[indexMin] = temp;
    }
  }
}

const arr = [5,4,3,2,1]
arr.selectionSort();
console.log(arr);//[ 1, 2, 3, 4, 5 ]

// selectionSort: O(n^2)

3.插入排序

insertionSort: O(n^2)
将第一个元素标记为已排序,遍历每个没有排序的元素,“提取”该元素,将它与前面已排序的元素进行比较,找到它应该放置的位置,并将它插入进去。

Array.prototype.insertionSort = function() {
  //console.log(this);//这里的this就是自己的数组,比如这里输出的是[ 5, 4, 3, 2, 1 ]
  for(let i = 1; i < this.length; i +=1) {
    const temp = this[i];
    let j = i;
    while(j>0) {
      //因为要插入j,所以要让前面的值都向后挪一位
      if(this[j - 1] > temp) {
        this[j] = this[j-1];
      }else {
        break;
      }
      j -= 1;
    }
    //此时下标为j的地方就是应该插入的地方
    this[j] = temp;
  }
}

const arr = [5,7,3,9,1]
arr.insertionSort();
console.log(arr);//[ 1, 3, 5, 7, 9 ]

// insertionSort: O(n^2)

4.归并排序

它采用了分治策略,将数组分成2个较小的数组,然后每个数组再分成两个更小的数组,直至每个数组里只包含一个元素,然后将小数组不断的合并成较大的数组,直至只剩下一个数组,就是排序完成后的数组序列。
实现步骤:

  • 将原始序列平分成两个小数组
  • 判断小数组⻓度是否为1,不为1则继续分裂
  • 原始数组被分称了⻓度为1的多个小数组,然后合并相邻小数组(有序合并)
  • 不断合并小数组,直到合并称一个数组,则为排序后的数组序列

时间复杂度:O(n*log2n)

function mergeSort(arr) {
  let array = mergeSortRec(arr);
  return array;
}

function mergeSortRec(arr) {
  let length = arr.length
  if(length === 1) {
    return arr
  }
  let mid = Math.floor(length/2),
      left = arr.slice(0, mid),
      right = arr.slice(mid, length)
  return merge(mergeSortRec(left), mergeSortRec(right))
}

//顺序合并两个小数组left、right 到 result
function merge(left, right) {
  let result = [],
      ileft = 0,
      iright = 0
  while(ileft < left.length && iright < right.length) {
    if(left[ileft] < right[iright]) {
      result.push(left[ileft++])
    }else {
      result.push(right[iright++])
    }
  }
  while(ileft < left.length) {
    result.push(left[ileft++])
  }
  while(iright < right.length) {
    result.push(right[iright++])
  }
  return result
}

let arr = [1,2,8,0,6]
console.log(mergeSort(arr));//[ 0, 1, 2, 6, 8 ]

代码二

Array.prototype.insertionSort = function() {
  //console.log(this);//这里的this就是自己的数组,比如这里输出的是[ 5, 4, 3, 2, 1 ]
  //定义一个递归函数
  const rec = (arr) => {
    if(arr.length === 1) {return arr;}
    const mid = Math.floor(arr.length/2)
    const left = arr.slice(0,mid)
    const right = arr.slice(mid, arr.length)
    const orderLeft = rec(left)
    const orderRight = rec(right)
    const res = []
    while(orderLeft.length || orderRight.length) {
      if(orderLeft.length && orderRight.length) {
        res.push(orderLeft[0] < orderRight[0] ? orderLeft.shift() : orderRight.shift())
      } else if(orderLeft.length) {
        res.push(orderLeft.shift())
      } else if(orderRight.length) {
        res.push(orderRight.shift())
      }
    }
    return res
  }
  //执行递归函数
  const res = rec(this)
  //改变原数组,this指向的是传入的arr,n是对应的值,i是下标
  //res数组中存放的是已经排好序的数组,将res的每个值传给this数组
  res.forEach((n, i) => {this[i] = n})
}

const arr = [5,7,3,9,1]
arr.insertionSort();
console.log(arr);//[ 1, 3, 5, 7, 9 ]

5.快速排序

原理
和归并排序一致,它也使用了分治策略的思想,它也将数组分成一个个小数组,但与归并不同的是,
它实际上并没有将它们分隔开。
快排使用了分治策略的思想,所谓分治,顾名思义,就是分而治之,将一个复杂的问题,分成两个或
多个相似的子问题,在把子问题分成更小的子问题,直到更小的子问题可以简单求解,求解子问题,
则原问题的解则为子问题解的合并。

快排的过程简单的说只有三步:
首先从序列中选取一个数作为基准数
将比这个数大的数全部放到它的右边,把小于或者等于它的数全部放到它的左边 (一次快排
partition )
然后分别对基准的左右两边重复以上的操作,直到数组完全排序

具体按以下步骤实现:

  • 创建两个指针分别指向数组的最左端以及最右端
  • 在数组中任意取出一个元素作为基准
  • 左指针开始向右移动,遇到比基准大的停止
  • 右指针开始向左移动,遇到比基准小的元素停止,交换左右指针所指向的元素
  • 重复3,4,直到左指针超过右指针,此时,比基准小的值就都会放在基准的左边,比基准大
    的值会出现在基准的右边
  • 然后分别对基准的左右两边重复以上的操作,直到数组完全排序

时间复杂度:O(n*log2n)

function quick(arr){
  if(arr.length <= 1){
      return arr;
  }
  var left = [],
      right = [],
      mid = arr[0];
  for(let i = 1;i < arr.length; i++){
    if(arr[i] > mid){
      right.push(arr[i]);
    }else{
      left.push(arr[i]);
    }
  }
  // return quick(left).concat([mid],quick(right));
  return [...quick(left),mid,...quick(right)]
}

const arr = [5,3,7,0,6]
console.log(quick(arr));//[ 0, 3, 5, 6, 7 ]

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序媛小y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值