Ex1_3_37 Josephus问题

  1. import edu.princeton.cs.algs4.StdIn;
  2. import edu.princeton.cs.algs4.StdOut;
  3. //使用由循环单链表实现的队列完成
  4. public class Ex1_3_37_Josephus<Item> {
  5. private class Node{
  6. Item item;
  7. Node next;
  8. }
  9. private int size;
  10. private Node last;
  11. public boolean isEmpty(){ return size == 0; }//last.next不可用
  12. public int size(){ return size; }
  13. public void enqueue(Item item){
  14. Node oldLast = last;
  15. last = new Node();
  16. last.item = item;
  17. if(isEmpty()) last.next = last;
  18. else{
  19. last.next = oldLast.next;
  20. oldLast.next = last;
  21. }
  22. size++;
  23. }
  24. public Item dequeue() {
  25. Item item = last.next.item;
  26. size--;
  27. if (isEmpty()) last = null;
  28. else {
  29. last.next = last.next.next;
  30. }
  31. return item;
  32. }
  33. //测试用例
  34. public static void main(String[] args){
  35. Ex1_3_37_Josephus Queue = new Ex1_3_37_Josephus();
  36. int N = Integer.parseInt(args[0]);
  37. int M = Integer.parseInt(args[1]);
  38. for(int i = 0; i < N; i++){ Queue.enqueue(i); }
  39. for(int i = 0; i < N; i++){
  40. Ex1_3_37_Josephus.Node node = Queue.last.next;
  41. for(int j = 0; j < M-2; j++){
  42. node = node.next;
  43. }
  44. Queue.last = node;
  45. StdOut.println(Queue.dequeue());
  46. }
  47. }//当N=7, M=2时输出1 3 5 0 4 2 6, 6号位最后一个
  48. }

要点

  1. Queue除了使用有first和last节点的链表实现,还可以使用只有last节点的循环链表实现
  2. 这种实现中,isEmpty()不能使用last.next == null判断,因为dequeue()和enqueue()中last.next开始总等于null
  3. 实现思路:每次需要删除规定位次的结点,只能动态改变头结点(尾节点)引用的指向
  1. for(int i = 0; i < N; i++){
  2. CircleLinkList.Node node = linkList.last.next;//找出当前头结点
  3. for(int j = 0; j < M-2; j++){//根据规定的位次找到当前头结点下规定位次节点
  4. node = node.next;
  5. }
  6. linkList.last = node;//为方便删除,让被找出节点成为头节点(实际上找出尾节点,头结点自动形成)
  7. StdOut.println(linkList.dequeue());//删除并打印
  8. }