【发布时间】:2010-09-21 20:13:17
【问题描述】:
我在 C 中有一个循环的、静态分配的缓冲区,我将其用作 depth 广度优先搜索的队列。我希望对队列中的前 N 个元素进行排序。只使用常规的 qsort() 会很容易——除了它是一个循环缓冲区,并且前 N 个元素可能会环绕。当然,我可以编写自己的排序实现,它使用模运算并知道如何环绕数组,但我一直认为编写排序函数是一个很好的练习,但最好留给库。
我想到了几种方法:
- 使用单独的线性缓冲区 - 首先从循环缓冲区复制元素,然后应用 qsort,然后将它们复制回来。使用额外的缓冲区意味着额外的 O(N) 空间需求,这让我
- 使用 qsort 对“顶部”和“底部”两半进行排序,然后使用附加缓冲区将它们合并
- 与 2 相同,但在原地进行最终合并(我没有发现太多关于原地合并的信息,但我看到的实现似乎不值得降低空间复杂度)
另一方面,花一个小时思考如何优雅地避免编写我自己的快速排序,而不是添加那 25 行(左右)行可能也不是最有效率的......
更正:在切换 DFS 和 BFS 时犯了一个愚蠢的错误(我更喜欢编写 DFS,但在这种特殊情况下我必须使用 BFS),很抱歉造成混淆。
原问题的进一步描述:
我正在实现 breadth 优先搜索(寻找与fifteen 拼图不同的东西,只是更复杂,每个状态大约有 O(n^2) 个可能的扩展,而不是 4 个)。 “蛮力”算法已经完成,但它是“愚蠢的”——在每一点,它以硬编码的顺序扩展所有有效状态。队列实现为循环缓冲区(无符号队列[MAXLENGTH]),它将整数索引存储到状态表中。除了两个简单的函数来对索引进行排队和出队之外,它没有任何封装——它只是一个简单的、静态分配的无符号数组。
现在我想添加一些启发式方法。我想尝试的第一件事是在展开后对展开的子状态进行排序(“以更好的顺序展开它们”)——就像我正在编写一个简单的最佳优先 DFS 一样。为此,我想加入队列(代表最近的扩展状态),并使用某种启发式方法对它们进行排序。我还可以以不同的顺序扩展状态(因此在这种情况下,如果我打破队列的 FIFO 属性并不重要)。
我的目标不是实现A* 或基于深度优先搜索的算法(我无法扩展所有状态,但如果我不这样做,我将开始遇到状态无限循环的问题空间,所以我不得不使用iterative deepening之类的东西。
【问题讨论】:
-
这不是 O(n) 空间要求。这是一个 O(N) 额外的空间要求,其中 N 是您实际需要排序的数量。我猜 N 很小。
-
@tgamblin:我看到我选择了相反的大小写约定。我只能说:Bbzzzzzzt。就这样!
-
有人可以帮我整理文章的格式吗?出于某种原因,十五个谜题的链接没有终止(但在预览中还可以,所以我不知道那里出了什么问题)。
-
@tgamblin - 你说得对,我应该选择不同的字母,而不是使用 n/N。
-
@Kim - 链接问题已修复。 SO 对 URL 真的很愚蠢,en.wikipedia.org/wiki/A*_search_algorithm URL 中的星号使它很适合,所以我把它的 URL 缩小了。
标签: c algorithm sorting circular-buffer