代码之家  ›  专栏  ›  技术社区  ›  Bad Request

保存内存的合并排序

  •  1
  • Bad Request  · 技术社区  · 14 年前

    我在上算法课,最新的作业真的让我难堪。本质上,赋值是实现一个merge sort版本,它不会像clr中的实现那样分配那么多临时内存。我应该在开始时只创建一个临时数组,然后在拆分和合并时将所有临时内容放入其中。

    我还应该注意,类的语言是Lua,这一点很重要,因为唯一可用的数据结构是表。它们就像Java映射一样,它们以键-值对的形式出现,但它们就像数组一样,不必成对插入——如果只插入一个被视为值的东西,那么它的键就是它的索引在一个有真正数组的语言中是什么。至少我是这样理解的,因为我对Lua也是新手。而且,任何东西,原语、字符串、对象等都可以是一个键,甚至是同一个表中的不同类型。

    总之,有两件事让我困惑:

    首先,怎么做?你只是用每次拆分和合并的递归来覆盖临时数组吗?

    1. 编写一个顶级过程merge_sort,它的参数是ar- 雷来分类。它应该声明一个临时数组,然后调用merge-sort-1, 一个由四个参数组成的过程:要排序的数组,用作tem的数组- poraly空间,以及在其中调用 合并排序1应该可以工作。

    2. 间隔,并为每一半对自身进行递归调用。在那之后 调用merge合并这两部分。 现在编写的合并过程将是 数组和临时数组、开始、中点和结束。 它在临时数组中维护一个索引,在每个数组中维护索引i,j 它需要从头到尾遍历临时数组,复制 从永久数组的下半部分或 如果小于或等于上半部分j处的值,则为一半,并且 前进i.如果小于,它选择上半部分j处的值 下半部分的值是i,然后前进j。 永久数组的一部分用完后,请确保复制其余部分 另一部分。教科书使用了一个具有无限值的技巧 避免检查任何一部分是否用完。不过,这个把戏很难 在这里申请,你会把它放在哪里? 最后,在临时数组中从头到尾复制所有值

    第2个问题让人困惑,因为我不知道merge-sort-1应该做什么,以及为什么它必须是一个不同于merge-sort的方法。我也不知道为什么需要传递起始索引和结束索引。事实上,也许我读错了一些东西,但是指令听起来像merge_sort_1,并没有做任何真正的工作。

    另外,整个赋值也很混乱,因为我从指令中看不到将原始数组分成两半的过程。还是我误解了梅格索特?

    3 回复  |  直到 14 年前
        1
  •  0
  •   gwell    14 年前

    首先,怎么做?你…吗 继续覆盖临时数组 合并?

    是的,临时数组一直被覆盖。在合并阶段使用临时数组保存合并结果,然后在合并结束时将其复制回永久数组。

    第二个让人困惑,因为我 为什么它必须是 与合并排序不同的方法。

    merge_sort_1 merge_sort 只是一个方便的函数,创建临时数组并填充初始的开始和结束位置。

    我也不知道为什么 已通过开始和结束索引。在 事实上,也许我读错了什么,但是 指令听起来像 合并排序1不做任何实际工作。

    因为我看不到 拆分位置的说明 做两个原来的一半 合并排序?

    递归函数 合并排序1

    我可以用Lua编写合并排序,并且可以对我的实现进行评论。这些指示似乎是通过书面形式写出来的,就好像是对教师执行情况的评论。

    这是 合并排序 功能。正如我所说,这只是一个方便的功能,我觉得不是肉的问题。

    -- Write a top level procedure merge_sort that takes as its argument
    -- the array to sort.
    function merge_sort(a)
        -- It should declare a temporary array and then call merge_sort_1,
        -- a procedure of four arguments: The array to sort, the one to use
        -- as temporary space, and the start and finish indexes within which
        -- this call to merge_sort_1 should work.
        merge_sort_1(a,{},1,#a)
    end
    
        2
  •  1
  •   Theo Belaire    14 年前


    看看 this 解释,用花哨的动画来帮助你理解它。

    这是他们的伪代码版本:

    # split in half
    m = n / 2
    
    # recursive sorts
    sort a[1..m]
    sort a[m+1..n]
    
    # merge sorted sub-arrays using temp array
    b = copy of a[1..m]
    i = 1, j = m+1, k = 1
    while i <= m and j <= n,
        a[k++] = (a[j] < b[i]) ? a[j++] : b[i++]
        → invariant: a[1..k] in final position
    while i <= m,
        a[k++] = b[i++]
        → invariant: a[1..k] in final position
    

    看看他们如何使用b来保存数据的临时副本? 你的老师想要的是你把一张桌子交进去,用来临时存放。

    这能解决任务吗?

        3
  •  1
  •   Keith Randall    14 年前

    您的主要排序例程如下:(对不起,我不知道Lua,所以我将编写一些Javaish代码)

    void merge_sort(int[] array) {
      int[] t = ...allocate a temporary array...
      merge_sort_1(array, 0, array.length, t);
    }
    

    merge_sort_1 获取要排序的数组、一些开始和完成索引以及用于某些临时空间的数组。它执行实际的分而治之的调用,并调用 merge 例行公事。注意,递归调用需要转到 合并排序1 而不是 merge_sort

    我会让你写一个 合并