JS撸算法:冒泡排序

177 阅读2分钟

冒泡排序

思路

遍历数组,每次对比当前元素与下一元素,按对比结果调整当前元素与下一元素的位置。

每次遍历,我们符合顺序的元素就会冒泡到最后一位,所以遍历数组长度次,排序完成。

例子

把数组从小到大排序。

首先我们需要遍历数组,然后对比当前元素与下一个位置元素的大小,如果当前元素大于下一个元素,就交换位置,相等或小于不用交换。

每次遍历都会有一个元素冒泡出来完成排序,所以遍历数组长度次数(两次循环)即可。

冒泡排序过程如下图所示:

js实现

其实我们还可以做一个优化,如果遍历一次没有元素交换的话,说明我们的元素全部排序完成了,可以终止接下来的无效循环。


function swap(data, i, j) { 
  let temp = data[i];
  data[i] = data[j];
  data[j] = temp;
}

function sort(data) {
  if (data.length < 2) return;

  let bubbleLength = data.length;
  let hasSwap = true; // 是否交换标记

  while(bubbleLength && hasSwap) {
    let swaped = false;
    for(let j = 0; j < bubbleLength; j++) {
      if(data[j] > data[j + 1]) {
        swap(data, j, j + 1);
        swaped = true;
      }
    }
    bubbleLength--;
    hasSwap = swaped;
  }

}

测试

接下来使用jest进行测试


// 创建数组
function createArray(length: number) {
  const arr = [];
  for(let i = 0; i < length; i++) {
    arr.push(Math.floor(Math.random()*100));
  }
  return arr;
}

describe('test sort', () => {
  
  test('amount number sort', () => {
    const data = createArray(10);
    const newData = [...data];
    const dataSorted = newData.sort((a ,b) => a - b);
    sort(data);
    expect(data).toMatchObject(dataSorted);
  })

  test('empty number sort', () => {
    const data: number[] = [];
    const dataSorted: number[] = [];
    sort(data);
    expect(data).toMatchObject(dataSorted);
  })

  test('one number sort', () => {
    const data = [1];
    const dataSorted = [1];
    sort(data);
    expect(data).toMatchObject(dataSorted);
  })
  
})

全部通过

总结

冒泡排序的循环有两点可以优化

  1. 每次循环数量递减
  2. 如果没有交换产生时,说明所有元素排序完成,可以终止后面的循环。