js实现的大根堆算法(基于链式的m叉树)

2024-03-27 21:58
文章标签 算法 实现 js 链式 根堆

本文主要是介绍js实现的大根堆算法(基于链式的m叉树),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

面向过程版本

var COUNT = 3;
/*获取待排序数据,数据的个数和值随机生成
*/
function getData() {var arr = [];var i = 0;var len = Math.max(10, ~~(Math.random() * 30 ));while(i <  len) {arr.push(~~(Math.random() * 100 ));i++;}   return arr;
}
/*节点构造函数@param val {any} 节点的值@param position {int} 节点的位置,即第几个节点
*/
function Node(val, position) {// 叉数,例如二叉树var count = COUNT;// 初始化节点的孩子为nullwhile(count) {this[count--] = null;}this.position = position;// 父节点、前继节点、后继节点this.parent = null;this.pre = null;this.next = null;// 孩子个数this.childs = 0;this.val = val;
}
/*构造COUNT叉树
*/
function makeTree(arr) {var i = 1;var root = new Node(arr[0], 0);var position = 1;var count = COUNT;// 初始化队列var queue = [root];// 保存上一个遍历的节点,用于前后节点的连接var preNodePtr;// 构造m叉树完成后,从哪个节点开始遍历这棵树,从最后一个非叶子节点开始var neededNode;// 是否已经找到了最后一个非叶子节点var isFind = false;// 用于寻找最后的非叶子节点var preNode = root;// 利用队列进行广度遍历while(queue.length) {var node = queue.shift();i = 1;// 给当前节点配置孩子数据,个数为COUNTwhile(i <= count) {// 判断当前的节点数是否已经超过数据的长度if (position < arr.length) {var newNode = new Node(arr[position], position);node[i] = newNode;newNode.parent = node;newNode.pre = preNode;preNode.next = newNode;node.childs++;queue.push(newNode);preNode = newNode;i++;position++;} // 全部数据赋值完成else {break;}}// 是否找到了最后的非叶子节点if (!isFind) {// 当前节点的孩子数为0,说明前一节点为最后一个非叶子节点if (node.childs === 0) {neededNode = preNodePtr;isFind = true;return {root: root,startNode: neededNode};} // 当前节点的孩子数小于分支数COUNT,说明当前节点为最后的非叶子节点else if (node.childs < COUNT){neededNode = node;isFind = true;return {root: root,startNode: neededNode};}// 保存前一个节点else {preNodePtr = node;}}}return root;
}
// 找出一棵树的最后非叶子节点,已经在makeTree里实现
function findNode(root) {var queue = [root];var node;var count = COUNT;var i = 1;var preNodePtr;while(queue.length) {node = queue.shift();if (node.childs === 0) {return preNodePtr;} else if (node.childs < COUNT) {return node;}preNodePtr = node;while(i <= count) {queue.push(node[i++]);}count = COUNT;  }
}
// 根据一颗无序的m叉树构建m叉大堆树
function buildHeapTree(root, startNode) {var node = startNode;// 从最后一个非叶子节点开始,到根节点结束,遍历其中的所有节点,调整成m叉堆的形式,最后根节点为值最大的节点while(node) {adjustHeapTree(node);node = node.pre;}return root;
}
// 以node节点为根节点,endNode为结束节点。把node子树调整成m叉堆,
function adjustHeapTree(node, endNode) {var i = 1;var max = node.val;var position = 0;var isEnd = false;while(i <= COUNT) {// 是否已经到达了结束节点,是则结束所有步骤if (endNode && node[i] && node[i].position >= endNode.position) {isEnd = true;break;}// 找到node节点和孩子中的最大值。if (node[i] && node[i].val > max) {max = node[i].val;position = i;}i++;}var temp;// 如果node节点的值不是最大的,那么和值最大的孩子节点进行值的互换if (position !== 0) {temp = node.val;node.val = node[position].val;node[position].val = temp;/*是否已经到达结束节点,是的话不需要再进行调整后续的子树,因为孩子节点的position和父节点的大以被置换值的孩子节点为根节点,调整成m叉树   */!isEnd && adjustHeapTree(node[position], endNode);}   
}/*对排序的主流程
*/
function heapSort(root, startNode) {if (!root.childs) {return;}var node = startNode;// 获取整个树的最后一个节点,即最后一个非叶子节点的最后一个节点var lastChild = getNodeLastChild(node);var endNode = lastChild;var temp;// 首先构建m叉堆buildHeapTree(root, startNode);while(endNode !== root) {// 把m叉堆中值最大的节点,即根节点的值和最后一个孩子的值互换temp = root.val;root.val = endNode.val;endNode.val = temp;// 以根节点为起点,endNode为终点,调整子树为m叉堆adjustHeapTree(root, endNode);// 终点根节点方向,往前挪一位,此时,endNode后面的节点都是有序的endNode = endNode.pre;}
}
// 或许某个节点的最后一个孩子节点
function getNodeLastChild(node) {var count = COUNT;while(count) {if (node[count]) {return node[count];}count--;}return null;
}
// 广度遍历root为根节点的m叉树
function echo(root) {var queue =[root];var result = [];var i = 1;while(queue.length) {i = 1;var node = queue.shift();result.push(node.val);while(i <= node.childs) {queue.push(node[i++]);}}console.log('sort: data',JSON.stringify(result),'\n');return result;
}
// 断言堆排序算法产生的数据是升序的
function assert(result) {var i = 0;while(i < result.length - 2) {if (result[i] > result[i+1]) {console.log('error',i, result,'\n');break;}i++;}
}
function start() {var data = getData();console.log('source data:',JSON.stringify(data));var {root, startNode} = makeTree(data);heapSort(root, startNode);assert(echo(root));
}
start();

粗糙的面向对象版本

function HeapSort(count) {this.data = [];this.COUNT = count || 2;
}HeapSort.prototype = {getData: function() {var arr = [];var i = 0;var len = Math.max(10, ~~(Math.random() * 30 ));while(i <  len) {arr.push(~~(Math.random() * 100 ));i++;}   this.data = arr;return arr;},makeTree: function makeTree() {var arr = this.data;var i = 1;var root = this.getNode(arr[0], 0);var position = 1;var count = this.COUNT;var queue = [root];var preNodePtr;var neededNode;var isFind = false;var preNode = root;while(queue.length) {var node = queue.shift();i = 1;while(i <= count) {if (position < arr.length) {var newNode = this.getNode(arr[position], position);node[i] = newNode;newNode.parent = node;newNode.pre = preNode;preNode.next = newNode;node.childs++;queue.push(newNode);preNode = newNode;i++;position++;} else {break;}}if (!isFind) {if (node.childs === 0) {neededNode = preNodePtr;isFind = true;this.startNode = neededNode;this.root = root;} else if (node.childs < this.COUNT){neededNode = node;isFind = true;this.startNode = neededNode;this.root = root;} else {preNodePtr = node;}}}return root;},findNode: function findNode(root) {var queue = [root];var node;var count = COUNT;var i = 1;var preNodePtr;while(queue.length) {node = queue.shift();if (node.childs === 0) {return preNodePtr;} else if (node.childs < this.COUNT) {return node;}preNodePtr = node;while(i <= count) {queue.push(node[i++]);}count = this.COUNT; }},buildHeapTree: function buildHeapTree() {var node = this.startNode;while(node) {this.adjustHeapTree(node);node = node.pre;}},adjustHeapTree: function adjustHeapTree(node, endNode) {var i = 1;var max = node.val;var position = 0;var isEnd = false;while(i <= this.COUNT) {if (endNode && node[i] && node[i].position >= endNode.position) {isEnd = true;break;}if (node[i] && node[i].val > max) {max = node[i].val;position = i;}i++;}var temp;if (position !== 0) {temp = node.val;node.val = node[position].val;node[position].val = temp;!isEnd && this.adjustHeapTree(node[position], endNode);}   },heapSort: function heapSort() {if (!this.root.childs) {return;}var root = this.root;var node = this.startNode;var lastChild = this.getNodeLastChild(node);var endNode = lastChild;var temp;this.buildHeapTree();while(endNode !== root) {temp = root.val;root.val = endNode.val;endNode.val = temp;this.adjustHeapTree(root, endNode);endNode = endNode.pre;}},getNodeLastChild: function getNodeLastChild(node) {var count = this.COUNT;while(count) {if (node[count]) {return node[count];}count--;}return null;},echo: function echo() {var queue =[this.root];var result = [];var i = 1;while(queue.length) {i = 1;var node = queue.shift();result.push(node.val);while(i <= node.childs) {queue.push(node[i++]);}}this.result = result;console.log('sort: data',JSON.stringify(result),'\n');},assert: function assert() {var result = this.result;var i = 0;while(i < result.length - 2) {if (result[i] > result[i+1]) {console.log('error',i, result,'\n');break;}i++;}},start: function start() {this.getData();console.log('source data:',JSON.stringify(this.data));this.makeTree();this.heapSort();this.echo();this.assert();},getNode(val, position) {var node = {};var count = this.COUNT;while(count) {node[count--] = null;}node.position = position;node.parent = null;node.pre = null;node.next = null;node.childs = 0;node.val = val;return node;}
}
new HeapSort().start();

算法正确性验证

var end = 10000;
var i = 0;
var time = setInterval(function() {if (i > end) {clearInterval(time);}i++;start();//new HeapSort().start();
},10)

算法性能比较

// 插入排序 
function insertSort(arr) {
for (var i = 1;i<arr.length;i++) {
var j=i-1;
var key = arr[i];
while (j>=0 && key<arr[j]) {
arr[j+1] = arr[j];
j--;
}
arr[j+1] = key;
}
}// 希尔排序
function shellSortRecursion(arr,step) {if(step<1) {return;}for (var i = step;i<arr.length;i++) {var j = i-step;var key = arr[i];while (j>=0 && key<arr[j]) {arr[j+step] = arr[j];j-=step;}arr[j+step] = key;}step = Math.floor(step/2);shellSortRecursion(arr,step);
}function start() {var data = getData();var start = new Date().getTime();var {root, startNode} = makeTree(data);heapSort(root, startNode);//insertSort(data)//shellSortRecursion(data,5)console.log((new Date().getTime() - start)/1000);
}
start();

这篇关于js实现的大根堆算法(基于链式的m叉树)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/853511

相关文章

使用Redis快速实现共享Session登录的详细步骤

《使用Redis快速实现共享Session登录的详细步骤》在Web开发中,Session通常用于存储用户的会话信息,允许用户在多个页面之间保持登录状态,Redis是一个开源的高性能键值数据库,广泛用于... 目录前言实现原理:步骤:使用Redis实现共享Session登录1. 引入Redis依赖2. 配置R

SpringBoot实现RSA+AES自动接口解密的实战指南

《SpringBoot实现RSA+AES自动接口解密的实战指南》在当今数据泄露频发的网络环境中,接口安全已成为开发者不可忽视的核心议题,RSA+AES混合加密方案因其安全性高、性能优越而被广泛采用,本... 目录一、项目依赖与环境准备1.1 Maven依赖配置1.2 密钥生成与配置二、加密工具类实现2.1

在Java中实现线程之间的数据共享的几种方式总结

《在Java中实现线程之间的数据共享的几种方式总结》在Java中实现线程间数据共享是并发编程的核心需求,但需要谨慎处理同步问题以避免竞态条件,本文通过代码示例给大家介绍了几种主要实现方式及其最佳实践,... 目录1. 共享变量与同步机制2. 轻量级通信机制3. 线程安全容器4. 线程局部变量(ThreadL

python使用Akshare与Streamlit实现股票估值分析教程(图文代码)

《python使用Akshare与Streamlit实现股票估值分析教程(图文代码)》入职测试中的一道题,要求:从Akshare下载某一个股票近十年的财务报表包括,资产负债表,利润表,现金流量表,保存... 目录一、前言二、核心知识点梳理1、Akshare数据获取2、Pandas数据处理3、Matplotl

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连

Python实现网格交易策略的过程

《Python实现网格交易策略的过程》本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一... 网格交易是一种经典的量化交易策略,其核心思想是在价格上下预设多个“网格”,当价格触发特定网格时执行买

python设置环境变量路径实现过程

《python设置环境变量路径实现过程》本文介绍设置Python路径的多种方法:临时设置(Windows用`set`,Linux/macOS用`export`)、永久设置(系统属性或shell配置文件... 目录设置python路径的方法临时设置环境变量(适用于当前会话)永久设置环境变量(Windows系统