数据结构和算法(三)

125 阅读2分钟

写在前面

上一篇博客实际上就是选择排序,每次找到最小的数放在前面,然后对后面的数做同样的事情

用循环的方式写选择排序

  • 算法永远可以用循环或递归的方式写
  • 所有递归都可以改成循环
  • 重写minIndex,相当于min
function minIndex(numbers){
    let index = 0
    for(let i = 0;i <= numbers.length;i++){
        if(numbers[i] <= numbers[index]){
            index = i
        }
    }
    return index
}

重写sort,swap待实现

function sort(numbers){
    for(let i = 0;i <= numbers.length;i++){
         let index = minIndex(numbers)
        swap(numbers,index,i) 
    }
}

实现swap

function swap(numbers i j){
    let temp = numbers[i]
    numbers[i] = numbers[j]
    numbers[j] = temp
}

大致写好后解决问题,每次给minIndex传递时应该削去已经排好的

function sort(numbers) {
  for (let i = 0; i <= ???; i++) {
    let index = minIndex(numbers.slice(1))+i;
    swap(numbers, index, i);
  }
}

  • slice 不会修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。
  • splice()方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组
  • 注意区别
function sort(numbers) {
  for (let i = 0; i < numbers.length-1; i++) {
    let index = minIndex(numbers.slice(i))+i;
    if(index!==i){
        swap(numbers, index, i);
    }
  }
  return numbers
}
  • 选择排序就是把最小值放到前面不管,对剩下的进行同样的操作

用递归的方式写快速排序

function quicksort(numbers) {
  if (numbers.length <= 1) {
    return numbers;
  } else {
    let pivotIndex = Math.floor(arr.length / 2);
    let pivot = numbers.splice(pivotIndex, 1)[0];
    let right = [];
    let left = [];
    for (let i = 0; i < numbers.length; i++) {
      if (numbers[i] < pivot) {
        left.push(numbers[i]);
      } else {
        right.push(numbers[i]);
      }
    }
    return quicksort(left).concat([pivot], quicksort(right));
  }
}

之后对两块分别快排

  • 快排让我知道,递归可以递归调用两次,先一分为二,分别递归

用递归的方式写归并排序

分成两队直到每队剩一个人相当于已经排好了
关键在于每次合并是都要排序,所以迭代时mergesort外面一点有个merge

function mergesort(numbers) {
  if (numbers.length === 1) {
    return numbers;
  }
  let left = arr.slice(0, Math.floor(numbers.length / 2));
  let right = arr.slice(Math.floor(numbers.length / 2));
  return merge(mergesort(left), mergesort)(right);
}
function merge(a, b) {
  if (a.length === 0) return b;
  if (b.length === 0) return a;
  if (a[0] > b[0]) {
    [b[0]].concat(merge(a, b.slice(1)));
  } else {
    [a[0]].concat(merge(a.slice(1), b));
  }
}

计数排序

function countSort(arr){
    let hashTable = {}
    max = 0
    result = []
    for(let i = 0;i <= numbers.length;i++){
       if(!(arr[i] in hashTable)){
           hashTable[arr[i]] = 1
       } else{
           hashTable[arr[i]] += 1
       }
    }
    if(arr[i] > max){
        max = arr[i]
    }
    //遍历数组得到哈希表和最大值
    for(let j =0;j <= max;j++){  //遍历哈希表
        if(j in hashTable){
        for(let i = 0;i <= hashTable[j];i++){
                result.push(j)
            }
        }
    }
    return result
}
  • 主要就是制造一个哈希表,并且用in来遍历哈希表
  • 分清楚key和value

时间复杂度

  • 选择排序0(n^2)
  • 快速排序O(n*log2 n)
  • 归并排序0(n*log2 n)
  • 计数排序0(n + max)
  • n次排序怎么样都必须排,乘一个衰落次数