Java:如何实现Dancing Links算法(使用DoublyLinkedLists)?

时间:2016-10-09 03:26:50

标签: java linked-list nodes doubly-linked-list knuth

我正在尝试用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

我在主要方法中做错了什么?

如何在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();

      ///////////////

这是DoublyLinkedList类:

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 个答案:

答案 0 :(得分:1)

我不熟悉Knuth的Dancing Links算法,但发现this article使得它很安静。特别是我发现这非常有用:

  

Knuth利用了双向链表的基本原则。   从列表中删除对象时,只需要执行两个操作:

     

x.getRight()。setLeft(x.getLeft())
  x.getLeft()。setRight(&gt; x.getRight())

     

但是,将对象放回列表中时,全部   需要做的是反向操作。

     

x.getRight()。setLeft(x)
  x.getLeft()。setRight(x)

     

一切都是   需要把对象放回来的是对象本身,因为对象   仍然指向列表中的元素。除非x的指针是   改变了,这个操作非常简单。


为了实现它,我添加了用于链接/取消链接的setter。看评论:

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();

          ///////////////
      }
    }