JavaScript堆排序
来源:互联网 发布:淘宝二级页面有什么用 编辑:程序博客网 时间:2024/05/22 04:51
构建堆
本文都是最大堆。利用数组存储堆中的元素,且堆中第一个元素序号为1,子元素小于父元素
如上图:对于第i
个节点,他的子节点为2i,2i+1
,父节点为i/2
,以数组存储堆。
1.直接插入
每当在数组末尾即最后一个叶子节点后面插入新元素,都可能破坏最大堆的性质,因此要调整堆,即比较新插入的元素和其父元素的大小,若大于父元素就和父元素交换位置,循环这个过程。
function Heap() { this.data = []; this.addPos = 1;//表示下一个可以插入的位值为addPos}} Heap.prototype = { addItem(item){//添加元素 this.data[this.addPos++] = item; this.shiftUp();//向上调整堆 }, shiftUp: function () { let k = this.addPos - 1; //this.addPos - 1表示最后一个元素,其大于父元素就和父元素交换,循环这个过程 while (k > 1 && this.data[Math.floor(k / 2)] < this.data[k]) { this.swap(Math.floor(k / 2), k); k = Math.floor(k / 2); } }, getMax(){//取堆顶元素即最大值并返回。 let max = this.data[1]; this.data[1] = this.data[--this.addPos];//将堆中最后一个元素赋值给堆顶元素。 this.shiftDown(1);//从堆中第1个元素开始调整堆 return max; }, shiftDown(k){ while (2 * k < this.addPos) {//如果第k个元素有子节点 let j = 2 * k;//j表示孩子节点中的最大值的索引,先取左孩子节点 if (j + 1 < this.addPos && this.data[j + 1] > this.data[j]) {//若存在右孩子节点并且右孩子结点大于左孩子节点 j += 1; } if (this.data[j] > this.data[k]) {//若第k个元素小于孩子节点,就将其和最大的孩子节点交换位置 this.swap(k, j); } else { break; } k = j; } }, getSize(){ return this.data.length; }, showPrint(){ for (let i = 0; i < this.data.length; i++) { console.log(this.data[i]); } }, swap(a, b){ let temp = this.data[a]; this.data[a] = this.data[b]; this.data[b] = temp; },};
每次取一个元素插入到堆中,即对每个元素进行shiftUp操作,则生成堆的时间复杂度为O(nlogn);
测试:
let heap = new Heap();let arr = [1,4,0,3,5,8];for(let i = 0;i<arr.length;i++){ let item = arr[i]; heap.addItem(item);}heap.showPrint();console.log('_____________________________');let len = heap.addPos;for(let i = 0;i<len;i++){ if(heap.addPos !== 1){ let max = heap.getMax(); console.log(max) }}
输出结果为:
845130_____________________________854310
2.从最后一个非叶子节点调整
即将传进来的arr按照原先的顺序写成2叉树,从最后一个非叶子节点开始进行shiftDown操作,即使其子元素满足最大堆的性质。
function Heap(arr) { this.data = []; this.addPos = 1; this.init(arr);}Heap.prototype = { init(arr){ this.data[0] = undefined; this.data = this.data.concat(arr.slice(0)); this.addPos = this.data.length; let firstNoLeaf = parseInt((this.addPos - 1) / 2); for (let i = firstNoLeaf; i > 0; i--) { this.shiftDown(i); } }, swap(a, b){ let temp = this.data[a]; this.data[a] = this.data[b]; this.data[b] = temp; }, shiftDown(k){ while (2 * k < this.addPos) { let j = 2 * k; if (j + 1 < this.addPos && this.data[j + 1] > this.data[j]) { j += 1; } if (this.data[j] > this.data[k]) { this.swap(k, j); } else { break; } k = j; } }, getMax(){ let max = this.data[1]; this.data[1] = this.data[--this.addPos]; this.shiftDown(1); return max; }, showPrint(){ for (let i = 1; i < this.addPos; i++) { console.log(this.data[i]); } }};
直接将传进来的数组从最后一个非叶子节点开始,依次向前,作为根节点进行
shiftDown
操作,则生成堆的时间复杂度为O(nlogn)
;
测试:
let arr = [1, 4, 0, 3, 5, 8];let heap = new Heap(arr);heap.showPrint();console.log('_____________________________');let len = heap.addPos;for (let i = 0; i < len; i++) { if (heap.addPos !== 1) { let max = heap.getMax(); console.log(max) }}
输出:
851340_____________________________854310
不开辟新空间的堆排序
在上面2中init
方法中构建完最大堆后,取堆顶元素(最大值)和最后一个元素交换,同时将堆的长度减1,即最后一个元素的位置已经固定,以后不需要调整,然后调整堆,然后再从堆顶开始调整堆。
function init(arr){ this.data[0] = undefined; this.data = this.data.concat(arr.slice(0)); this.addPos = this.data.length; let firstNoLeaf = parseInt((this.addPos - 1) / 2); for (let i = firstNoLeaf; i > 0; i--) { this.shiftDown(i);//注意这里虽然shiftDown的时间复杂度为O(logn),但是其内只进行了一次判断,并未循环,因此时间复杂度为O(n) //以上是将arr调整成堆 } for (let i = this.addPos - 1; i > 0; i--) { this.swap(1, i); this.addPos--; this.shiftDown(1);//这里从第一个元素开始调整需要循环调整,因此时间复杂度为O(logn) }//此时this.data 中的数据已经是排好序的了 },
先利用2中的方法将数组调整成最大堆后,依次将堆中第一个元素和最后一个元素交换,此时,最后一个元素为最大值,
且其位置已经固定,堆长度减一,接着调整堆,重复前面的工作,这样的好处是不用开辟新的空间。速度最快,时间复杂度为O(nlogn)
阅读全文
0 0
- 堆排序javascript实现
- JavaScript堆排序
- 堆排序之JavaScript实现
- JavaScript数据结构之 堆排序
- (七)JavaScript实现堆排序
- 选择排序---堆排序算法(Javascript版)
- javascript 冒泡排序法 插入排序法 选择排序法 归并排序法 堆排序法
- 堆及堆排序
- 堆/堆排序特点
- 【二叉堆、堆排序】
- 二叉堆 & 堆排序
- 二叉堆 & 堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 解决ajax返回值给外部函数问题
- 洛谷1781
- oracle rac 遇到insert append导致gc current request夯住
- JVM高级特性与实践(十二):高效并发时的内外存交互、三大特征(原子、可见、有序性) 与 volatile型变量特殊规则
- 数据源与连接池关系
- JavaScript堆排序
- 数据结构之--------数组
- api-ms-win-crt-runtimel1-1-0.dll缺失的解决方案
- [RK3288][Android6.0] WiFi之NetworkMonitor对评分机制的影响
- 手把手教你如何搭建CTS测试环境---1、Ubantu U盘启动制作及安装
- 2017福建省赛Problem B Triangles(判断两三角形位置关系)
- JVM 优化浅解分析
- JavaScript打印Excel、Word
- eclipse使用tomcat maven插件 Edit Source Lookup Path