Day 26: Insertion sort & Selection sort

我们先来用insertion sort algorithm来解题。
虽然他的效率也不高,但这是很好理解且实作的演算法。
偷渡一下队友的一篇好文 演算法入门理解
下面我就直接叙述insertion sort实作的流程!

先随便给一个阵列 Array = [5, 2, 3, 9, 3]
我们从阵列中第一个元素开始拜访,

  1. [ 5 ]

    先把5暂定在第一个位置,接着往第2个数拜访
    可以想像我们用一个sublist来当作已经排序好的数列

  2. [ 5, 2]
    因为 5 > 2,所以两个交换(swap)

  3. [ 2, 5] 接着继续到第3个数

  4. [ 2, 5, 3] 因为 5 > 3,所以 swap
    [ 2, 3 ,5] 然後2!>3,所以不动

  5. [ 2, 3, 5, 9] 因为5 !> 9,不用动
    且前面3个数都已经是排序过的,就不用再做检查

  6. 自己试试看最後一步应该会是怎麽样swap吧!

应该是 [ 2, 3, 5, 9, 3] → [ 2, 3, 5, 3, 9] → [ 2, 3, 3, 5, 9] 对吧?

很明显我们上面的操作都是in place ,所以 空间复杂度O(1)
而平均时间复杂度会是 O(n^2), n是我们array的长度

最後来看程序码的实作

function insertionSort(array) {
  for( let i = 1; i < array.length; i++){
//一开始 tmp = 1 取 array[1] 和 array[0]比较
		let tmp = i;
		while(tmp > 0 && array[tmp] < array[tmp - 1]){
			swap(tmp, tmp-1, array);
			tmp -= 1;
		}
	}
	return array;
}

const swap = (i, j, array) =>{
	const tmp = array[j];
	array[j] = array[i];
	array[i] = tmp;
}

看完Insertion sort,直接来看Selection sort的执行步骤。

我们一开始就看整个阵列,代表着完全尚未被排序的阵列[5, 2, 3, 9, 3] (目前是整个阵列都是unsorted subarray)
我们把整个array非排序过的数上个色
[ 5, 2, 3, 9, 3 ]

接着我们扫过整个array,取出最小的数,把他和array中还没被排序的sublist第一个数交换(swap)。

第一回合中,我们找到2。於是我们就把 2 和 5 swap

[2 , 5, 3, 9, 3] 现在2就是我们已经排序过的sublist
而剩下的就是我们尚未排序的sublist。

第二回合,我们找到 3,所以再把 3,5 swap 得到 [2 , 3, 5, 9, 3]

接着同理操作 [2 , 3, 3,9, 5 ] → [2 , 3, 3, 5, 9 ] → [2 , 3, 3, 5, 9 ]
很明显我们上面的操作都是in place ,所以 空间复杂度O(1)
而平均时间复杂度会是 O(n^2), n是我们array的长度

最後来看程序码的实作

function selectionSort(array) {
  let startIndex = 0;
  while (startIndex < array.length - 1) {
    //纪录最小数字的index
    let smallestNumIndex = startIndex;
    for (let i = startIndex + 1; i < array.length; i++) {
      if (array[smallestNumIndex] > array[i]) smallestNumIndex = i;
    }
    swap(startIndex, smallestNumIndex, array);
    startIndex++;
  }
  return array;
}

const swap = (i, j, array) => {
  const tmp = array[j];
  array[j] = array[i];
  array[i] = tmp;
};

不知道有没有人跟我一样一开始学这两个算法时,超常把他们搞相反!/images/emoticon/emoticon06.gif
建议大家也多coding几次,虽然每次都是选最小的数来交换位置,但最大的差异是一开始在挑选比较的样本基准上不一样喔。

明日预告:Quick Sort


<<:  【Day 26】NumPy (3):Slicing, Copy, View, shape, Concatenate

>>:  Day26 - 移除没用到的 CSS,使用 Purge CSS (feat. Ant Design, Tailwind)

【设计+切版30天实作】|Day24 - Steps区块 - 如何做出渐层背景?

前面完成了「Pros」区块,今天来完成「Steps」的区块。 数据收集 标题的样式 Font-we...

企业资料通讯Week7 (2) | rdt(reliable data transfer)[下]

rdt3.0 rdt3.0 开始考虑到packet loss的情形,它怎麽解决呢? 喔喔~原来是采用...

倒数第二天

终於到了倒数第二天 现在一直在努力的写前後端的程序码跟串接 在前端 RxDB 中有一些 Middle...

予焦啦!附录:旅途拾贝

今天是 Hoddarla 系列文中的附录第 0 篇。笔者在这一年半的准备期当中送了两个 patch ...

day11 : argo gitops服务以及ingress (上)

花了好几天终於完成了所有的基础设施,接着就可以开始部署服务以及使用了,对於k8s来说要部署服务需要的...