归并排序可以节省内存
我正在学习算法课程,最近的作业让我很头疼。基本上,这个任务是要我实现一种版本的归并排序,它不需要像 CLRS 中的实现一样分配太多的临时内存。我应该通过一开始只创建一个临时数组,并在拆分和合并时将所有临时内容放入其中来实现这一点。
我还应该注意到,这个班级的语言是 Lua,这很重要,因为唯一可用的数据结构是表格。它们像 Java 映射一样以键值对形式出现,但它们像数组一样,如果只插入一个东西,它将被视为一个值,它的键将是在具有真实数组的语言中的索引。至少这是我理解的方式,因为我也是新手。此外,任何东西,原语、字符串、对象等都可以作为键——甚至是同一个表中的不同类型。
无论如何,有两件事让我困惑:
首先,它是如何完成的?你只是在每次拆分和合并的递归中用临时数组覆盖吗?
第二,我真的对作业说明感到困惑(我正在免费地旁听课程,所以无法询问任何工作人员)。这里是说明:
1.编写一个顶层过程merge_sort
,它以要排序的数组作为参数。它应该声明一个临时数组,然后调用merge_sort_1
,merge_sort_1
是一个具有四个参数的过程:要排序的数组、用作临时空间的数组,以及此调用中merge_sort_1
应该工作的开始和结束索引。
2.现在编写merge_sort_1
,它计算开始和结束间隔的中点,并为每个半部分递归调用自身。在此之后,它调用merge
来合并这两个半部分。你现在写的合并过程将是永久数组和临时数组、开始、中点和结束的函数。它在临时数组中维护一个索引,并在永久数组的每个(已排序)半部分中维护索引i
、j
。它需要从开始到结束遍历临时数组,从永久数组的较低半部分或较高半部分中复制一个值。如果较低半部分中的i
的值小于或等于较高半部分中的j
的值,则选择较低半部分中的i
的值,并运行i
。如果较高半部分中的值j
小于较低半部分中的值,则选择较高半部分中的j
的值,并运行j
。在使用一个部分的永久数组后,确保复制另一个部分的其余部分。此处教科书使用一个无限值 ∞ 技巧来避免检查两个部分是否被使用完。然而,这个技巧很难应用于这里,因为你应该把它放在哪里呢?最后,将临时数组中从开始到结束的所有值都复制回永久数组中。
第二个让我困惑,因为我不知道merge_sort_1
应该做什么,为什么它必须与merge_sort
不同。我也不知道为什么它需要传递起始和结束索引。实际上,也许我读错了什么,但说明听起来像merge_sort_1
不做任何实际的工作。
此外,整个作业很困惑,因为我没有看到从说明中拆分原始数组以制作两个半部分。或者我是否误解了归并排序的思想?
希望我表述的有些意义。谢谢大家!
原文链接 https://stackoverflow.com/questions/4103769
你的主要排序程序看起来像这样:(抱歉,我不知道 Lua,所以我会写一些类似 Java 的代码)
void merge_sort(int[] array) {
int[] t = ...分配临时数组...
merge_sort_1(array, 0, array.length, t);
}
merge_sort_1
接受要排序的数组,一些起始和结束索引,以及用于一些临时空间的数组。它执行实际的分治调用和调用 merge
程序。请注意,递归调用需要调用 merge_sort_1
而不是 merge_sort
,因为您不希望在每个递归级别上分配数组,而是只需在归并排序过程的开始处分配一次。(这就是将归并排序分成两个程序的全部意义。)
我会留给你编写一个 merge
程序。它应该接受包含 2 个已排序子部分的原始数组和一个临时数组,并对原始数组进行排序。最简单的方法是将其合并到临时数组中,然后在完成时只需将其复制回来。
首先,好吧,它是如何完成的?您是否只需在每个拆分和合并的递归中重写临时数组?
是的,临时数组会不断被覆盖。在合并阶段,临时数组用于保存合并结果,然后在合并结束时将其复制回永久数组中。
第二个问题很困惑,因为我不知道 merge_sort_1
应该做什么,为什么它必须是与 merge_sort
不同的方法。
merge_sort_1
是递归归并排序的递归中心。merge_sort
将作为一个方便的函数,创建临时数组并填充初始的开始和结束位置。
我也不知道为什么它需要传递起始和终止索引。实际上,也许我误读了一些东西,但是这些说明听起来好像 merge_sort_1
并没有做任何实际工作。
此外,整个任务很困惑,因为我从说明中看不出在哪里进行分割以使原始数组分为两半。或者我是否误解了归并排序?
递归函数 merge_sort_1
仅处理传入数组的一部分。它处理的部分由开始和结束索引定义。开始和结束之间的中点是分割数组的方式,然后在递归调用中再次分割。在完成上半部分和下半部分的递归调用后,将两个半部分合并到临时数组中,然后将其复制回永久数组中。
我能够按照描述写出 Lua 版本的归并排序,并可以对我的实现进行评论。似乎说明像是对教师实现的注释或评论。
这是 merge_sort
函数。正如我所说,它只是一个方便的函数,我认为它不是问题的关键。
-- 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
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
首先,我会确保你理解归并排序。
看看这里的解释,里面有漂亮的动画帮助你理解它。
这是他们的伪代码版本:
#分割成两半 m = n / 2 #递归排序 sort a [1 .. m] sort a [m + 1..n] #使用临时数组合并排序后的子数组 b = 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 ++] →不变式:a [1..k]处于最终位置 while i <= m, a [k ++] = b [i ++] →不变式:a [1..k]处于最终位置
看看他们如何使用b来保存一份数据的临时副本? 你的老师想要的是你传入一个表来用于这个临时存储。
这样清楚了这个任务吗?