Day14:堆积排序(Heap Sort)

堆积(Heap)

堆积,是一种树状结构,用於实现「优先伫列(Priority queue)」。Priority queue是资料结构的一种,可以自由追加数据,读取资料时,从最小值开始选取。
堆积是一种完整的二元树,储存在一维阵列内,分成MaxHeap及MinHeap。

  • MaxHeap:上一层的节点数值>=下一层的所有节点
  • MinHeap:上一层的节点数值<=下一层的所有节点

https://ithelp.ithome.com.tw/upload/images/20210914/201282861fh3JDRK1K.png

建立Heap步骤如下:

  1. 先将一维阵列转换为Heap结构
    • 由小到大排序:使用MaxHeap
    • 由大到小排序:使用MinHeap
  2. 从堆积结构依序取出Root,与最後一的元素交换,再将除了最後一个节点外的一维阵列转换成堆积结构,重复执行直到剩下最後一个元素,排序完成。

堆积排序(Heap Sort)

  • 堆积排序最初要将n个数储存到堆积中的时间是O(n log(n))。
  • 此外,每回合取出最大值,再重新排列堆积,所需时间是O(log n),回合数是n,堆积重整後接着排序的执行时间也是O(n log(n)),由此得知,堆积排序的整体执行时间是O(n log(n))。
  • 与气泡排序、选择排序、插入结构相比,堆积排序处理速度较快,但也因为这种复杂的资料结构,建置与维护变得复杂。
import random

#从1-100中随机读取8个数字
nums = random.sample(range(1,100), 9)
print(nums)

def max_heapify(h, n, x):
    #如果(2*x+1) <= n,表示有右子节点
    if (2*x+1) <= n :
        #如果h[2*x] > h[2*x+1],表示左子节点大於右子节点
        if h[2*x] > h[2*x+1]:
            max = 2*x
        else:
            max = 2*x+1
    else:
        max = 2*x
    #如果h[x]<h[max],则两个子节点互换
    if h[x] < h[max]:
        h[x], h[max] = h[max], h[x]
        #如果2*max<=n,表示h[max]也有子节点,recursion max_heapify是否与孙节点互换
        if 2*max <= n:
            max_heapify(h, n, max)

#将任何阵列转换为Max Heap
def build_max_heap(h, n):
    #回圈变数
    for i in range(n//2, 0, -1):
        max_heapify(h, n, i)

def heap_sort(h, n):
    build_max_heap(h, len(h)-1)
    print(h)
    for i in range(n, 1, -1):
        h[i], h[1] = h[1], h[i]
        if i > 2:
            max_heapify(h, i-1, 1)
        print(h)

heap_sort(nums, len(nums)-1)
print(nums)
let heapSize;
let arr = [15, 3, 17, 18, 20, 2, 1, 666];
heapSort();
console.log(arr);

function buildMaxHeap() {
  heapSize = arr.length - 1;
  for (let i = Math.floor(heapSize / 2); i >= 0; i--) {
    maxHeapify(i);
  }
}

function maxHeapify(i) {
  let largest;
  let l = i * 2 + 1;
  let r = i * 2 + 2;
  if (l <= heapSize && arr[l] > arr[i]) {
    largest = l;
  } else {
    largest = i;
  }

  if (r <= heapSize && arr[r] > arr[largest]) {
    largest = r;
  }

  if (largest != i) {
    // swap A[i] with A[largest]
    let temp = arr[i];
    arr[i] = arr[largest];
    arr[largest] = temp;
    maxHeapify(largest);
  }
}

function heapSort() {
  buildMaxHeap();
  for (let i = arr.length - 1; i >= 0; i--) {
    // exchange A[0] with A[i]
    let temp = arr[0];
    arr[0] = arr[i];
    arr[i] = temp;
    heapSize -= 1;
    maxHeapify(0);
  }

  return arr;
}

结论

排序演算法到今天告一个段落,明天要开始新的演算法,下表整理了这几天的排序演算法:

https://ithelp.ithome.com.tw/upload/images/20210914/20128286ZLA64ODuaD.png

後续会再继续补充资料,目前先这样吧!


<<:  D-0-结束也是开始,这30天dotnetcore的历程回顾

>>:  成员 2 人:别公平、别相爱、别把友情当应该

水深火热CSS Day 1

不难发现,问题在於该用什麽标准来做决定呢?梁晓声曾讲过,友谊,好比一瓶酒,封存的时间越长,价值则越高...

DAY 26:Proxy Pattern,让代理人操作实际的物件

什麽是 Proxy Pattern? 让代理物件操作实际物件,让代理物件处理与业务逻辑无关的事情 U...

方法论之间的差异:敏捷与瀑布

任何软件应用程序的开发都采用一种系统方法,该方法涉及从规划到部署的多个步骤,该方法称为软件开发生命周...

DAY11: Node基础总整理

前几篇的互相比较来比较去的,是不是都有点乱了思绪,今天来做个小复习,从DAY5: node 的内部机...

Day28-机器学习(2) KNN

KNN简单说明 为一种监督学习的方法,其原理就好像物以类聚一样,相同的东西会聚在一起 我们可以设定一...