总访问量: PV

DataScience && DataMining && BigData

约瑟夫环问题1求解

约瑟夫环问题:
* 背景:约瑟夫叙述了他和40个士兵在罗马战争期间被罗马军队包围之后签订的一人自杀协定。
* 约瑟夫建议每个人杀掉他旁边的人,约瑟夫利用制定的规则使自己成为这些人中唯一的幸存者。
* 编程:

   1.考虑存储结构:顺序存储结构和链式存储结构(杀人模拟删除节点,链表更适合)
   2.场景:程序需要处理8个士兵组成的线性表,因为每个人要杀掉他的邻居,则要保证
   每个人都有邻居,因此采用循环单链表操作,指针指向的位置表示邻居。
   3.核心思想:从循环单链表中某个节点开始依次去除其相邻节点,直到链表中剩下一个节点为止

 ##思考使用循环双链表及奇数的情况

1.循环单链表数据结构

  1 package com.neusoft.link;
  2 import com.neusoft.List.IList;
  3 /**
  4  * @author zhao-chj
  5  * 循环单链表
  6  */
  7 public class CircleLinkList implements IList{
  8     public Node head;
  9     public CircleLinkList() {
 10         // TODO 初始化
 11         head=new Node();//初始化头结点
 12         head.next=head;
 13     }
 14     @Override
 15     public void clear() {
 16         // TODO 清空
 17         head.next=head;
 18     }
 19     @Override
 20     public boolean isEmpty() {
 21         // TODO 判空
 22         return head.next.equals(head);
 23     }
 24     @Override
 25     public int length() {
 26         // TODO 长度
 27         Node p =head.next;
 28         int length=0;
 29         while (!p.equals(head)) {
 30             p=p.next;
 31             length++;
 32         }
 33         return length;
 34     }
 35     @Override
 36     public Object get(int i) {
 37         // TODO 读取带头结点的循环链表中第i个数据元素
 38         Node p=head.next;
 39         int j=0;
 40         while (!p.equals(head)&&j<i) {
 41             p=p.next;
 42             j++;
 43         }
 44         if (j>i||p.equals(head)) {
 45             System.out.println("第"+i+"个元素不存在!");
 46         }
 47         return p.data;
 48     }
 49 
 50     @Override
 51     public void insert(int i, Object x) {
 52         // TODO 带头结点的循环链表中第i个节点之前插入一个值为x的元素
 53         Node p = head;
 54         int j=-1;//第i个节点前驱位置
 55         while ((!p.equals(head)||j==-1)&&j<i-1) {
 56             p=p.next;
 57             j++;
 58         }
 59         if (j>i-1||(p.equals(head)&&j!=-1)) {
 60             System.out.println("插入位置不合法!");
 61         }
 62         Node s =new Node(x);
 63         s.next=p.next;
 64         p.next=s;
 65     }
 66 
 67     @Override
 68     public void remove(int i) {
 69         // TODO 移除循环单链表中第i个元素的节点,注意i的范围
 70         Node p=head;//p指向要删除节点的前驱节点
 71         int j=-1;
 72         while ((!p.next.equals(head)||j==-1)&&j<i-1) {//找前驱元素
 73             p=p.next;
 74             j++;
 75         }
 76         if (j>i-1||(p.next.equals(head)&&j!=-1)) {
 77             System.out.println("删除位置不合法!");
 78         }
 79         p.next=p.next.next;
 80     }
 81 
 82     @Override
 83     public int indexOf(Object x) {
 84         // TODO 查找值为x的元素,返回位置
 85         Node p =head.next;//p指向首节点
 86         int j=0;
 87         while ((!p.equals(head))&&(!p.data.equals(x))) {
 88             p=p.next;
 89             j++;
 90         }
 91         if (!p.equals(head)) {
 92             return j;
 93         }else {
 94             return -1;
 95         }
 96     }
 97     @Override
 98     public void display() {
 99         // TODO 输出元素
100         Node p =head.next;
101         while (!p.equals(head)) {
102             System.out.print(p.data+" ");
103             p=p.next;
104         }
105         System.out.println();
106     }
107 
108     @Override
109     public int remove(Object i) {
110         // TODO Auto-generated method stub
111         return 0;
112     }
113 
114 }
点击+展开代码

2.约瑟夫环循环单链表求解

 1 package com.neusoft.exercise;
 2 
 3 import java.util.Scanner;
 4 
 5 import com.neusoft.link.CircleLinkList;
 6 
 7 /**
 8  * @author zhao-chj
 9  * 约瑟夫环问题:
10  * 来源:约瑟夫叙述了他和40个士兵在罗马战争期间被罗马军队包围之后签订的一人自杀协定。
11  * 约瑟夫建议每个人杀掉他旁边的人,约瑟夫利用制定的规则使自己成为这些人中唯一的幸存者。
12  * 编程:1.考虑存储结构:顺序存储结构和链式存储结构(杀人模拟删除节点,链表更适合)
13  *     2.场景:程序需要处理8个士兵组成的线性表,因为每个人要杀掉他的邻居,则要保证
14  *     每个人都有邻居,因此采用循环单链表操作,指针指向的位置表示邻居。
15  *     ##可以考虑使用循环双链表
16  *     3.核心思想:从循环单链表中某个节点开始依次去除其相邻节点,直到链表中剩下一个节点为止
17  *     
18  */
19 public class TestLinearTable06 {
20     public static void main(String[] args) {
21         CircleLinkList circleLinkList = new CircleLinkList();
22         Scanner sc = new Scanner(System.in);
23         System.out.println("请您输入士兵的个数~");
24         int num = sc.nextInt();
25         System.out.println(num+"士兵分别为:");
26         for (int i = 0; i < num; i++) {
27             //输入num个士兵
28             circleLinkList.insert(i, sc.next());
29         }
30         for (int i = 0; circleLinkList.length()>1; ) {
31             i = i%circleLinkList.length();
32             System.out.println("长度:"+circleLinkList.length());//测试用可注释
33             //读取到链表中位序号为i的士兵
34             String str1= circleLinkList.get(i).toString();
35             System.out.println("STR1:"+str1);//测试用可注释
36             //求出相邻士兵在链表中的位序号
37             i=++i%circleLinkList.length();
38             //相邻的士兵
39             String str2 =circleLinkList.get(i).toString();
40             System.out.println("STR2:"+str2);//测试用可注释
41             //杀死相邻的士兵
42             circleLinkList.remove(i);
43             //输出谁杀死谁的信息
44             System.out.println(str1+"杀死"+str2);
45         }
46         System.out.println("活着的是(约瑟夫)是:"+circleLinkList.get(0));
47     }
48 }

3.结果测试

  •     1.加入一些输出语句的测试

    

  •     2.不带输出语句的测试

   

 

posted @ 2017-03-22 13:11  CJZhaoSimons  阅读(493)  评论(0编辑  收藏  举报