博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
js实现的大根堆算法(基于链式的m叉树)
阅读量:6695 次
发布时间:2019-06-25

本文共 8511 字,大约阅读时间需要 28 分钟。

面向过程版本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;	// 初始化节点的孩子为null	while(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;		// 给当前节点配置孩子数据,个数为COUNT		while(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
=0 && key
=0 && key

转载于:https://juejin.im/post/5c3e049f6fb9a049b22223fb

你可能感兴趣的文章
复杂软件驱动系统的UCM与UML
查看>>
【转载】安装PyInstaller的方法和遇到的问题
查看>>
SQL(mysql)通过生日字段得到年龄
查看>>
css中box-sizing的使用心得
查看>>
C# 文件下载四方法
查看>>
Spring JDBC最佳实践(3)
查看>>
windows Socket 通信模型
查看>>
jquery validate案例1
查看>>
Redis应用场景
查看>>
不想工作的一天
查看>>
tomcat查看错误日志
查看>>
关于Jfinal中ContextPathHandler的作用
查看>>
从规范去看Function.prototype.apply到底是怎么工作的?
查看>>
音效原理
查看>>
FFmepg中文例子—指导2:加入音频
查看>>
cocos2dx 3.0 项目部署到android
查看>>
jenkins集成findBugs并生成报告
查看>>
恢复被误操作的~/.bashrc
查看>>
jfinal接口开发的一些要点
查看>>
socket上传输大文件时,如何能提高传输的效率?
查看>>