「这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战」
堆-代码讲解
介绍
堆 的介绍,在上篇已经讲过了 数据结构-堆,想先了解概念的小伙伴,可以先了解下什么是 堆。这样也便于下边对 堆 代码的一个理解。
问题
在 数据结构-堆 这篇文章中,暴露出来的问题,就是一个 非 堆 的数组,如何用 js代码 的形式转化成一个 堆 数组。
这是上篇文章用到的 非 堆 图,这里引用下来。
可以看到 这个 完全二叉树 数组的值为 [7,15,1,20,2,9,3,6]。
那如何得到我们想要的 堆 的图的结果呢,结果图:
这个 堆 的结果为 [20,15,3,7,9,2,1,6]。
从 [7,15,1,20,2,9,3,6] ---> [20,15,3,7,9,2,1,6] 的转化,我们下面用代码的形式讲解下。
注:这里重点补充一下,代码结果可能跟图上的不一样
-
因为打乱后的数据是随便写的,也就是随机的。如果想恢复成一模一样,就不是随机,就要添加相关的约束规则,来产生数据。
-
图上最终的结果 只是起到参考类比的作用,但最终的结果的结构都是 数据结构 堆
解决
主要是通过循环遍历的思想来解决。配合公式
-
当前节点:i
-
父节点: Math.floor((i-1)/2)
-
两个子节点分别为:
-
左孩子:2i + 1
-
右孩子: 2i+2
-
-
再通过 循环重新赋值,依次向上查找,直至退出循环
-
代码如下
const dataArray = [] // 初始化数据 const initDataArray = (arr) => { arr.forEach((item) => { insert(item) }) } // 获取 当前元素 的 父元素 下标 const getFatherIndex = (index) => { return Math.floor((index - 1) / 2) } // 交换值 const isExchange = (currentIndex, currentFatherIndex) => { const temp = dataArray[currentFatherIndex] dataArray[currentFatherIndex] = dataArray[currentIndex] dataArray[currentIndex] = temp } // 插入新元素 const insert = (value) => { dataArray.push(value) // 获取 当前元素 的 下标 let currentIndex = dataArray.length - 1 // 获取 当前元素 的 父元素 下标 let currentFatherIndex = getFatherIndex(currentIndex) // 判断 元素的父元素的下标是否存在 while (currentFatherIndex >= 0) { // 如果 当前元素 的值 大于 当前元素的父元素 的值,进行交换操作 if (dataArray[currentIndex] > dataArray[currentFatherIndex]) { isExchange(currentIndex, currentFatherIndex) } // 更新 当前元素下标 和 父元素下标 currentIndex = currentFatherIndex currentFatherIndex = getFatherIndex(currentIndex) } } // 输出 const print = () => { console.log(dataArray) } // initDataArray([20, 15, 3, 7, 9, 2, 1, 6]) initDataArray([7, 15, 1, 20, 2, 9, 3, 6]) print()