【问题标题】:How to merge sorted arrays within arrays into a third sorted array如何将数组中的排序数组合并到第三个排序数组中
【发布时间】:2017-02-20 15:21:51
【问题描述】:

由于我还是初学者,因此标题可能令人困惑并请原谅我。这是学校 HW 作业的一部分,虽然我没有直接寻找答案,但我需要朝着正确的方向推进,或者根本不需要任何帮助。那么问题来了……

我需要根据类中的代码创建一个简单的程序,将多个排序后的数组合并为一个排序后的数组输出到屏幕。数组被硬编码为“测试用例”以取消注释和验证。导师指导如下

使用在课堂上开发的合并程序(见附件)作为基础,创建一个将 0(零)合并到 n 个数字数组的版本。 提示: 合并前对数组进行排序 使用 shift 方法移除数组中的第一项 (arrayName.shift()) 创建数组数组---> var x = [ ];变量 y = [ ];变量 z = [ x, y ];

编辑:我已根据@cpugourou 给出的答案通过电子邮件向讲师发送了解决方案,他的答复是他不会接受该解决方案。作业的重点是手动合并这些数组。

下面是我们在课堂上开发的原始“合并程序”

"use strict";   // reduces chance for error

/* 
    there are 2 arrays here and this program will merge them.
    Your job is to merge zero or more arrays. Test cases include:
    1. arrays with no elements: x = [], y = [], z = [], ...
    2. 2 arrays - one with elements and one without: x = [], y = [200, 39,1]
    3. 4 arrays: x = [5, 1, 0], y = [], z = [78, 3], w = [4, 34]
*/
var x = [ 12, 5, 1], y = [ 13, 2, 3], z = [];   // x and y are input and, after processing, z has the merged arrays
var ix = 0, iy = 0, iz = 0;         // indexes to the next element

// The following sorts the arrays in ascending sequence
x.sort(function(a, b){return a - b});
y.sort(function(a, b){return a - b});

while (ix < x.length || iy < y.length){     // while arrays x or y have elements

if (ix < x.length && iy < y.length){    // if both have elements, choose the lowest element

    if (x[ix] <= y[iy]){                // is the current element in array x less than the current element in y?
        z[iz] = x[ix];                  // choose x
        iz++;                           // point to the next space in z
        ix++;                           // ditto x
    } else{                             // choose y
        z[iz] = y[iy];                  
        iz++;                           // next
        iy++;                           // next
    }

} else if (ix < x.length){              // if only one has elements is it x?
    for (ix; ix < x.length; ix++){      // if so, move the rest of x to z
        z[iz] = x[ix];                  // copy current element in x
        iz++;                           // next z ... no need to increment x because the for loop does it
    }

} else if (iy < y.length){              // if only y has elements
    for (iy; iy < y.length; iy++){      // move the rest of y to z
        z[iz] = y[iy];                  // copy
        iz++;                           // increment z's pointer
    }
}
}

// display the resulting merged elements in the web page
var result = "<ul>";
for (var i in z){
    result += "<li>" + z[i] + "</li>"
}
result += "</ul>"
document.getElementById("placeAnswerHere").innerHTML=result;

/*
Things to think about:
. This code is hard wired to merge only 2 arrays
. You will need to create an array containing all arrays to be merged. e.g. q = [x, y, z, w, and more]
. Your loop will need to find the smallest element in any of the arrays in q and move it to z (the resultant array)
. There is a method shift() to strip the first element from an array (e.g. x.shift(); removes the first element in array x)
. This is like making a pile of cafeteria trays from a variable numbers of tray stacks.
. Remember to sort all arrays first
*/

所以我的新问题变成了,如何在不编写一堆意大利面条代码的情况下完成此任务?

【问题讨论】:

  • 您需要将所有数组合并为一个数组,删除重复项,然后从低到高排序正确吗?
  • 是的,我认为我们不必删除重复项。
  • 如果你有一个可以处理两个数组的merge(a, b) 函数,你可以通过merge(a, merge(b, merge(c, d))) 简单地将它扩展到四个数组。如果您有任意多个数组,请使用循环。
  • OP 你能在编辑中发布这个在课堂上开发的假定合并工具吗?
  • 谢谢,但它应该是一个单独的代码块,同时仍保留您发布的原始代码。但是哇,我重申我之前关于你老师真的很愚蠢的评论。

标签: javascript arrays sorting merge


【解决方案1】:

我能想到的最快最短的(增加了重复数据):

var x = [5, 1, 0], y = [2, 5, 0], z = [78, 3, 1], w = [4, 34];

function sortNumber(a,b) {
    return a - b;
}
function uniq(a) {
   return Array.from(new Set(a));
}

var d = uniq(x.concat(y,z,w).sort(sortNumber));
/* [0, 1, 2, 3, 4, 5, 34, 78] */

【讨论】:

  • 啊!你打败了我......你的老师也很糟糕。真的很愚蠢。
  • 无论您使用何种语言,最重要的规则是避免使用意大利面条式代码。这是我见过的最好的意大利面条代码之一。在我的世界里,你的老师会因为教这种愚蠢的东西而被立即解雇。
  • 任务不傻。愚蠢的是老师对代码缺乏了解。还记得这位老师正在为未来一代工程师建模……您希望他们加入您的团队吗?
  • 啊哈,他真的很好!
  • @cpugourou 是的,OP 发布的代码很糟糕,但据我了解,这是他的代码而不是老师的代码?
【解决方案2】:

尽管 cpugorou 的答案有效,但它似乎与所述的硬件分配不匹配。至于硬件分配,我不清楚的一个问题是如何创建一个通用数组数组(例如 for(i = 0; i

忽略如何创建硬编码数组的通用数组的问题,一旦你有一个排序数组的数组,硬件分配似乎希望你使用数组数组实现 n 路合并。这意味着找到数组数组中的哪个数组具有最小元素并将该元素移动到输出数组(附加到输出数组,从输入数组中删除)。当 n 个数组中的一个被清空时,该数组将从数组数组中删除,然后您继续进行 n-1 路合并。重复此操作,直到只剩下 1 个数组,最后一个数组的其余部分被复制(或移动)到输出数组。

n 路合并的一个常见优化是使用堆,但我怀疑您是否应该为这个硬件分配使用堆。

【讨论】:

  • 硬件作业仍然是假的,代码是可怕的,老师仍然是愚蠢的。 OP 可能仍然会得到 F,因为当老师意识到自己陷入过去时,他的自尊心会受到伤害。但话说回来,大多数大学 CS 课程就是这样。
  • @Darkrum - n 路合并,通常使用堆,对于外部排序相当常见,例如 gnu 排序,它首先创建一组排序的临时文件,然后在临时文件上重复执行 16 路合并文件,直到最终合并产生排序的输出文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-10
  • 2011-08-22
  • 2022-01-16
  • 1970-01-01
  • 2016-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多