Java:如何实现 Dancing Links 算法(使用 DoublyLinkedLists)?
Posted
技术标签:
【中文标题】Java:如何实现 Dancing Links 算法(使用 DoublyLinkedLists)?【英文标题】:Java: How to implement Dancing Links algorithm (with DoublyLinkedLists)? 【发布时间】:2017-02-17 18:42:09 【问题描述】:我正在尝试用 Java 实现 Knuth 的 Dancing Links 算法。
根据 Knuth 的说法,如果 x
是一个节点,我可以通过 C 中的以下操作完全取消链接一个节点:
L[R[x]]<-L[x]
R[L[x]]<-R[x]
并通过以下方式恢复取消链接:
L[R[x]]<-x
R[L[x]]<-x
我在 main 方法中做错了什么?
如何在 Java 中实现取消链接和还原?
这是我的主要方法:
///////////////
DoublyLinkedList newList = new DoublyLinkedList();
for (int i = 0; i < 81; i++)
HashSet<Integer> set = new HashSet<Integer>();
set.add(i);
newList.addFirst(set);
newList.displayList();
// start at 69
newList.getAt(12).displayNode();
//HOW TO IMPLEMENT UNLINK?
//newList.getAt(12).previous() = newList.getAt(12).next().previous().previous();
//newList.getAt(12).next() = newList.getAt(12).previous().next().next();
newList.displayList();
//HOW TO IMPLEMENT REVERT UNLINK?
//newList.getAt(12) = newList.getAt(12).next().previous();
//newList.getAt(12) = newList.getAt(12).previous().next();
System.out.println();
///////////////
这里是 DoubleLinkedList 类:
public class DoublyLinkedList<T>
public Node<T> first = null;
public Node<T> last = null;
static class Node<T>
private T data;
private Node<T> next;
private Node<T> prev;
public Node(T data)
this.data = data;
public Node<T> get()
return this;
public Node<T> set(Node<T> node)
return node;
public Node<T> next()
return next;
public Node<T> previous()
return prev;
public void displayNode()
System.out.print(data + " ");
@Override
public String toString()
return data.toString();
public void addFirst(T data)
Node<T> newNode = new Node<T>(data);
if (isEmpty())
newNode.next = null;
newNode.prev = null;
first = newNode;
last = newNode;
else
first.prev = newNode;
newNode.next = first;
newNode.prev = null;
first = newNode;
public Node<T> getAt(int index)
Node<T> current = first;
int i = 1;
while (i < index)
current = current.next;
i++;
return current;
public boolean isEmpty()
return (first == null);
public void displayList()
Node<T> current = first;
while (current != null)
current.displayNode();
current = current.next;
System.out.println();
public void removeFirst()
if (!isEmpty())
Node<T> temp = first;
if (first.next == null)
first = null;
last = null;
else
first = first.next;
first.prev = null;
System.out.println(temp.toString() + " is popped from the list");
public void removeLast()
Node<T> temp = last;
if (!isEmpty())
if (first.next == null)
first = null;
last = null;
else
last = last.prev;
last.next = null;
System.out.println(temp.toString() + " is popped from the list");
【问题讨论】:
投了赞成票:一个很好的问题 【参考方案1】:我不熟悉 Knuth 的 Dancing Links 算法,但发现 this article 让我很清楚。特别是我发现这非常有帮助:
Knuth 利用了双向链表的基本原理。 从列表中删除对象时,只需要两个操作:
x.getRight().setLeft(x.getLeft()) x.getLeft().setRight(> x.getRight() )
但是,当将对象放回列表中时,所有 需要的是做相反的操作。
x.getRight().setLeft(x) x.getLeft().setRight(x)
所有的一切 需要把对象放回去是对象本身,因为对象 仍然指向列表中的元素。除非 x 的指针是 改了,这个操作很简单。
为了实现它,我添加了用于链接/取消链接的设置器。见 cmets:
import java.util.HashSet;
public class DoublyLinkedList<T>
public Node<T> first = null;
public Node<T> last = null;
static class Node<T>
private T data;
private Node<T> next;
private Node<T> prev;
public Node(T data)
this.data = data;
public Node<T> get()
return this;
public Node<T> set(Node<T> node)
return node;
public Node<T> next()
return next;
//add a setter
public void setNext(Node<T> node)
next = node;
public Node<T> previous()
return prev;
//add a setter
public void setPrevious(Node<T> node)
prev = node;
public void displayNode()
System.out.print(data + " ");
@Override
public String toString()
return data.toString();
public void addFirst(T data)
Node<T> newNode = new Node<T>(data);
if (isEmpty())
newNode.next = null;
newNode.prev = null;
first = newNode;
last = newNode;
else
first.prev = newNode;
newNode.next = first;
newNode.prev = null;
first = newNode;
public Node<T> getAt(int index)
Node<T> current = first;
int i = 1;
while (i < index)
current = current.next;
i++;
return current;
public boolean isEmpty()
return (first == null);
public void displayList()
Node<T> current = first;
while (current != null)
current.displayNode();
current = current.next;
System.out.println();
public void removeFirst()
if (!isEmpty())
Node<T> temp = first;
if (first.next == null)
first = null;
last = null;
else
first = first.next;
first.prev = null;
System.out.println(temp.toString() + " is popped from the list");
public void removeLast()
Node<T> temp = last;
if (!isEmpty())
if (first.next == null)
first = null;
last = null;
else
last = last.prev;
last.next = null;
System.out.println(temp.toString() + " is popped from the list");
public static void main(String[] args)
///////////////
DoublyLinkedList newList = new DoublyLinkedList();
for (int i = 0; i < 81; i++)
HashSet<Integer> set = new HashSet<Integer>();
set.add(i);
newList.addFirst(set);
newList.displayList();
// start at 69
Node node = newList.getAt(12);
node.displayNode(); System.out.println();
//HOW TO IMPLEMENT UNLINK?
node.previous().setNext(node.next);
node.next().setPrevious(node.previous());
//The 2 statements above are equivalent to
//Node p = node.previous();
//Node n = node.next();
//p.setNext(n);
//n.setPrevious(p);
newList.displayList();
//HOW TO IMPLEMENT REVERT UNLINK?
node.previous().setNext(node);
node.next().setPrevious(node);
newList.displayList(); System.out.println();
///////////////
【讨论】:
哇,谢谢!多么棒的解决方案。我想我得重温一下我的吸气剂和二传手了哈哈:P 我很高兴它有帮助。以上是关于Java:如何实现 Dancing Links 算法(使用 DoublyLinkedLists)?的主要内容,如果未能解决你的问题,请参考以下文章
ZOJ 3209 Treasure Map dancing links
HDU 5046 Airport ( Dancing Links 反复覆盖 )