堆排序实现进行了太多比较
Heapsort implementation does too many comparisons
我刚刚实现了堆排序算法。我的目标是尽可能少地进行比较。我的实现是有效的,但所做的比较是我在网上找到的这个示例的两倍多:http://www.csse.monash.edu.au/~劳埃德/波浪AlgDS/排序/堆/
测试阵列为:6 2 3 1 5 2 5 1 6 7 4 3 6 7 3 5 6 8 7 5 3 2 1 5
我在网上找到的样本进行了194次比较来对数组进行排序,我的实现进行了570次比较。
这里的代码:
$(document).ready(function(){
init();
});
var comparisons = 0;
var init = function()
{
var dataSource = getTestData();
var root = {value: dataSource[0]};
//Building heap
for(var i = 1; i < dataSource.length; i++)
addChild(root, {value: dataSource[i]});
console.log("--- Source: ---")
console.log(JSON.stringify(dataSource));
console.log("--- Input: ---")
console.log(JSON.stringify(dataSource));
console.log("--- Tree: ---")
console.log(JSON.stringify(root, null, 4));
console.log("Nodes: " + countChildren(root));
var sortedArray = new Array();
comparisons = 0;
//Do sorting here
while(countChildren(root) != 0){
sortNode(root); //Sorting heap
sortedArray.unshift(root.value); //Adding the biggest entry from the top of the heap to the output
deleteNode(root); //Removing the top of the heap
}
console.log("--- Sorted Tree: ---")
console.log(JSON.stringify(root, null, 4));
console.log("Nodes: " + countChildren(root));
console.log("--- Sorted: ---")
console.log(JSON.stringify(sortedArray));
console.log("!!! Comparisons: " + comparisons + " !!!");
}
var deleteNode = function(item)
{
if (item.left == null && item.right == null)
item.value = null;
else if (item.left != null) {
item.value = item.left.value;
if (countChildren(item.left) == 1)
item.left = null;
else
deleteNode(item.left)
}
else if (item.right != null) {
item.value = item.right.value;
if (countChildren(item.right) == 1)
item.right = null;
else
deleteNode(item.right)
}
}
var sortNode = function(item)
{
if (item.left != null && item.right == null){
sortNode(item.left);
comparisons++;
if (item.value < item.left.value) //Comparison
{
var tmp = item.value;
item.value = item.left.value;
item.left.value = tmp;
}
}else if (item.right != null && item.left == null){
sortNode(item.right);
comparisons++;
if (item.value < item.right.value) //Comparison
{
var tmp = item.value;
item.value = item.right.value;
item.right.value = tmp;
}
}
else if (item.right != null && item.left != null) {
sortNode(item.right);
sortNode(item.left);
//Some more comparisons
var left_bigger_right = (item.right.value <= item.left.value); comparisons++;
var left_bigger_this = (item.value < item.left.value); comparisons++;
var right_bigger_this = (item.value < item.right.value); comparisons++;
if ((left_bigger_this && left_bigger_right) || (right_bigger_this && left_bigger_right)) {
var tmp = item.value;
item.value = item.left.value;
item.left.value = tmp;
}
else if (right_bigger_this && left_bigger_right == false){
var tmp = item.value;
item.value = item.right.value;
item.right.value = tmp;
}
}
else{ //No children
//Nothing to do :)
}
}
var addChild = function(item, toAdd)
{
if(item.left == null)
item.left = toAdd;
else if (item.right == null)
item.right = toAdd;
else{ //if(item.left != null && item.right != null)
childrenCountLeft = countChildren(item.left);
childrenCountRight = countChildren(item.right);
if (childrenCountRight < childrenCountLeft)
addChild(item.right, toAdd);
else if (childrenCountLeft < childrenCountRight)
addChild(item.left, toAdd);
else //if (childrenCountLeft == childrenCountRight)
addChild(item.left, toAdd);
}
}
var countChildren = function(item){
var children = 0;
if (item.value != null)
children += 1;
if (item.left != null)
children += countChildren(item.left);
if (item.right != null)
children += countChildren(item.right);
return children;
}
var getTestData = function(){
return new Array(6 ,2 ,3 ,1 ,5 ,4 ,2 ,5 ,1 ,6 ,7 ,4 ,3 ,2 ,6 ,7 ,3 ,2 ,5 ,6 ,1 ,8 ,7 ,5 ,4 ,3 ,2 ,1 ,5);
}
我的问题是:我在哪方面没有实现堆排序算法?不必要的比较在哪里?
它们必须在sortNode函数中。我用评论把所有的比较都做了标记。
我不知道如何改进这个功能,减少比较。所以这将是我的问题。
您所实现的看起来不像堆排序(更准确地说,您所使用的数据结构不是一个合适的二进制堆)。
sortNode
函数总是对它的两个子函数进行递归调用,这导致始终遍历整个堆。这绝对不是堆的工作方式。因此,所有额外的比较都来自于不正确的算法(您的实现执行O(n ^ 2)
比较,而正确的实现应该只执行O(n log n)
)。
如何修复?正如我在上面所说的,你所知道的数据结构看起来不像堆,所以我建议从头开始正确地实现堆(你可以阅读维基百科的文章,以确保你正确地理解它)。
相关文章:
- 一个html元素的克隆次数太多
- ExtJS类的最佳实践最终导致了太多的.JS文件.性能怎么样
- 使用.slice分页选择了太多项目
- 堆排序实现进行了太多比较
- 如何在不每秒调用太多次的情况下通过Soundcloud解析api进行循环
- 如何修复“;太多递归”;ReactJS中的错误
- 为什么fs.readFile在windows上花费太多时间
- 如何避免webGL着色器加载给cpu带来太多负载
- node.js 需要太多的 TCP 套接字
- JavaScript循环迭代太多
- 函数崩溃,因为太多迭代jQuery
- 为什么不'当用户输入空格或字符太多/不够时,此函数会发出window.alert
- Angularjs:为什么重复做太多的工作
- Node.js错误:参数太多上传批量数据时出错
- ng重复调用控制器功能的次数太多
- 我正在验证一个联系人表单.我是不是过滤太多了
- Jquery-append函数花费了太多时间
- 为什么首先单击文档空白处的任何位置启动代码,而不是单击超链接,以及为什么打开了太多选项卡
- Facebook点赞按钮点赞太多了
- 加载事件中的“太多递归”