- 17
- 0
- 约3.44万字
- 约 28页
- 2018-06-01 发布于江苏
- 举报
dancing links完整中文翻译版1
Dancing Links 中文版
(DLXcn)
Donald E.Knuth, Stanford University
翻译 武汉武钢三中 吴豪
更正 排版 上海交通大学 隋清宇(sqybi)
目录
正文
精确覆盖问题
解决精确覆盖问题
舞蹈步骤
效率分析
应用于六形组
一个失败的试验
应用于四形条
应用于皇后问题
结语
致谢
历史注记
程序
参考资料
补注
译者的话
译者隋清宇的话
译者吴豪的话
感谢
声明及其它
正文
我写这篇论文的目的,是觉得这个简单的程序技巧理应得到广泛认可。假设 x
指向双向链的一个节点;L[x]和 R[x]分别表示 x 的前驱节点和后继节点。每个
程序员都知道如下操作:
L[R[x]] ← L[x], R[L[x]] ← R[x] (1)
是将 x 从链表删除的操作;但是只有少数程序员意识到如下操作:
L[R[x]] ← x, R[L[x]] ← x (2)
是把 x 重新链接到双向链中。
当然,指出这种操作以后,这个结果是显然的。但是,当我真正认识到操作(2)
的作用以后,我突然感到了定义“啊哈”这个词语时候的感觉,因为,L[x]和
R[x]的值在x 从链表中删除以后早已没有了它原来的语义。确实,一个精心设计
的程序在x 被删除后会通过把 L[x],R[x]赋值为 x 或者赋值为空值(null)来清
理掉这些不用的数据结构。而让一个链外的对象指向链本身有时具有潜在的危险
性。例如,指针就可以干扰垃圾回收机制的运作。
那么是什么关于操作(2)的研究促使我写一整篇论文来讨论这个问题呢?当x
从链表删除以后;为什么还要把它放回链表中?嗯,我承认,数据结构的更新通
常来说是永久性的。但是非永久性的更新也时常发生。例如,在一个交互性的程
序中,用户很可能想撤销他所做的一个或一系列操作,恢复到先前的状态。另一
个典型的应用是在回溯程序 (backtrack programs ) [16]里,回溯程序枚举约束
集合里的所有解。回溯,也叫深度优先搜索 (depth-first search),在之前的
论文中曾经讨论到。
操作(2)的观点是Hitotumatu 和 Noshita [22]于 1979 年提出的。他们提出
Dijkstra 提出的著名的解决 N 皇后问题 [6,第 72-82 页]的算法在使用了这个
技巧后,程序的速度比不使用几乎快了 2 倍。
Floyd 关于回溯和非确定性算法 [11]之间关联的优雅论述中包含详细的数据结
构更新与恢复的算法(谁能够提供这句话的准确翻译?——译者)。通常来说,
回溯程序可以被认为是一种搜索,所要做的就是缩小这个任务需要搜索的范围,
同时组织好用于控制搜索流程和决策的数据。对于多步的问题,解决问题的每一
步操作,都将改变剩余需要解决的问题。
简单情况下,我们可以考虑维护一个栈,用来保存当前搜索树节点之前的所有相
关状态信息,但是这个任务的拷贝动作需要耗时太多。因此,我们通常选用全局
数据结构。这样无论搜索进行到何种程度,它都会保留相关状态信息,并且当搜
索回溯的时候它都能恢复先前状态。
例如,Dijkstra 解决 n 皇后问题的递归算法将当前状态保存在三个全局布尔
(Boolean)数组中,他们分别表示棋盘上的列和2 条对角线;Hitotumatu 和
Noshita 的程序中使用双向链表来记录所有列和对角线上的可能性。当Dijkstra
算法暂时放置一个皇后在棋盘上的时候,会把每个布尔数组里的一个数据从真改
为假;回溯后又将这个数据改回真。Hitotumatu 和 Noshita 使用(1)去删除一
列,使用(2)去恢复删除操作;这意味着他们可以不通过搜索便找到一个空列。
程序通过这种方法记录下每个状态信息,这样替换和恢复节点使得 N 皇后问题的
计算更加高效。
算法(2)的优雅之处就在于我们仅仅知道x 的值就可以恢复(1)的操作。通常
来说要恢复操作,
原创力文档

文档评论(0)