总访问量: PV

DataScience && DataMining && BigData

约瑟夫环问题2(顺序表+链表求解)

1.背景知识   

* 古代判官要判决number个罪犯的死刑,制定了一条荒谬的法律
* 将犯人站成一个圈,从start开始数起,每数到第distance
* 个就处决他,依照此规律直到最后剩下一个人赦免。
* 如当number=5时候,start=0,distance=2时:
* 1.假设五个人是A B C D E
* 2.从A开始每隔两个处决一个人,依次处决
* 3.原始序列A(0) B(1) C(2) D(3) E(4)
* 第一次A(0) C(2) D(3) E(4) 干掉B(1),从c开始
* 第二次A(0) C(2) D(3) E(4) 干掉D(3),从e开始
* 第三次A(0) C(2) E(4) 干掉A(0),从c开始数
* 第四次C(2) E(4) 干掉E(4)
* 第五次C(2) c是被赦免的人

2.解法1:约瑟夫问题线性表存储结构解法

a.建立sequence线性存储结构

 1 package com.neusoft.chapter4.exercise;
 2 
 3 public class Sequence {
 4     public Object[] listElem;
 5     public int currentLen=0;//线性表长度
 6     public  Sequence(int maxSize) {
 7         currentLen =0;//线性表长度置空
 8         listElem = new Object[maxSize];
 9         //为顺序表分配存储空间
10     }
11     public void insert(int i, Object x) {
12         if (i<0 || i>currentLen) {
13             System.out.println("第"+i+"个元素不存在");
14         }
15         if (currentLen==listElem.length) {
16             System.out.println("顺序表容量已满");
17         }
18         for (int j = currentLen; j >i; j--) {
19             listElem[j]=listElem[j-1];
20         }
21         listElem[i]=x;
22         currentLen++;
23     }
24     public int length() {
25         return currentLen;
26     }
27     public Object get(int i) {
28         if (i<0 || i>currentLen-1) {
29             System.out.println("第"+i+"个元素不存在");
30         }
31         return listElem[i];
32     }
33     public Object remove(int i) {
34         // 将顺序表上的第i个元素a从顺序表中删除
35         Object listRemove=listElem[i];
36         if (i<0 ||i>=currentLen) {
37             System.out.println("删除位置不合法");
38         }
39         for (int j = i; j < currentLen-1; j++) {
40             listElem[j]=listElem[j+1];
41         }
42         currentLen--;
43         return listRemove;
44     }
45     public void display() {
46         for (int i = 0; i < currentLen; i++) {
47             System.out.print(listElem[i]+" ");
48         }
49         System.out.println();
50 
51     }
52 }

可点击下列代码复制

 1 package com.neusoft.chapter4.exercise;
 2 
 3 public class Sequence {
 4     public Object[] listElem;
 5     public int currentLen=0;//线性表长度
 6     public  Sequence(int maxSize) {
 7         currentLen =0;//线性表长度置空
 8         listElem = new Object[maxSize];
 9         //为顺序表分配存储空间
10     }
11     public void insert(int i, Object x) {
12         if (i<0 || i>currentLen) {
13             System.out.println("第"+i+"个元素不存在");
14         }
15         if (currentLen==listElem.length) {
16             System.out.println("顺序表容量已满");
17         }
18         for (int j = currentLen; j >i; j--) {
19             listElem[j]=listElem[j-1];
20         }
21         listElem[i]=x;
22         currentLen++;
23     }
24     public int length() {
25         return currentLen;
26     }
27     public Object get(int i) {
28         if (i<0 || i>currentLen-1) {
29             System.out.println("第"+i+"个元素不存在");
30         }
31         return listElem[i];
32     }
33     public Object remove(int i) {
34         // 将顺序表上的第i个元素a从顺序表中删除
35         Object listRemove=listElem[i];
36         if (i<0 ||i>=currentLen) {
37             System.out.println("删除位置不合法");
38         }
39         for (int j = i; j < currentLen-1; j++) {
40             listElem[j]=listElem[j+1];
41         }
42         currentLen--;
43         return listRemove;
44     }
45     public void display() {
46         for (int i = 0; i < currentLen; i++) {
47             System.out.print(listElem[i]+" ");
48         }
49         System.out.println();
50 
51     }
52 }
点击+展开代码

b.约瑟夫问题代码组织(主函数)

 1 package com.neusoft.chapter4.exercise;
 2 /**
 3  * @author zhao-chj
 4  * 古代判官要判决number个罪犯的死刑,制定了一条荒谬的法律
 5  *   将犯人站成一个圈,从start开始数起,每数到第distance
 6  * 个就处决他,依照此规律直到最后剩下一个人赦免。
 7  *   如当number=5时候,start=0,distance=2时:
 8  *   1.假设五个人是A B C D E
 9  *   2.从A开始每隔两个处决一个人,依次处决
10  *   3.原始序列A(0) B(1) C(2) D(3) E(4)
11  *      第一次A(0) C(2) D(3) E(4)  干掉B(1),从c开始
12  *      第二次A(0) C(2) D(3) E(4)  干掉D(3),从e开始
13  *      第三次A(0) C(2) E(4)  干掉A(0),从c开始数
14  *      第四次C(2) E(4)  干掉E(4)
15  *      第五次C(2)   c是被赦免的人
16  */
17 public class Josephus {
18     public static void main(String[] args) {
19         new Josephus(5, 0, 2);
20     }
21     public Josephus(int number,int start,int distance) {
22         // TODO 和类名相同的方法就是构造函数,是用于初始化变量的
23         System.out.println
24         ("Josephus("+number+","+start+","+distance+"),");
25         Sequence list =new Sequence(number);
26         //插入罪犯的名字,以A B C D为例
27         for (int i = 0; i < number; i++) {
28             list.insert(i,(char)('A'+i)+"");
29         }
30         //输出之前输入的罪犯名字,查看是否正确
31         list.display();
32         //计算起始位置
33         int i=start;
34         //找差别distance距离的元素或罪犯
35         while (list.length()>1) {
36             //处决间隔distance的元素或罪犯
37             i=(i+distance-1)%list.length();
38             System.out.print("删除"+list.remove(i).toString()+" ");
39             list.display();
40         }
41         System.out.println("被赦免者是"+list.get(0).toString());
42     }
43     
44     
45     
46 }

可点击下列代码复制

 1 package com.neusoft.chapter4.exercise;
 2 /**
 3  * @author zhao-chj
 4  * 古代判官要判决number个罪犯的死刑,制定了一条荒谬的法律
 5  *   将犯人站成一个圈,从start开始数起,每数到第distance
 6  * 个就处决他,依照此规律直到最后剩下一个人赦免。
 7  *   如当number=5时候,start=0,distance=2时:
 8  *   1.假设五个人是A B C D E
 9  *   2.从A开始每隔两个处决一个人,依次处决
10  *   3.原始序列A(0) B(1) C(2) D(3) E(4)
11  *      第一次A(0) C(2) D(3) E(4)  干掉B(1),从c开始
12  *      第二次A(0) C(2) D(3) E(4)  干掉D(3),从e开始
13  *      第三次A(0) C(2) E(4)  干掉A(0),从c开始数
14  *      第四次C(2) E(4)  干掉E(4)
15  *      第五次C(2)   c是被赦免的人
16  */
17 public class Josephus {
18     public static void main(String[] args) {
19         new Josephus(5, 0, 2);
20     }
21     public Josephus(int number,int start,int distance) {
22         // TODO 和类名相同的方法就是构造函数,是用于初始化变量的
23         System.out.println
24         ("Josephus("+number+","+start+","+distance+"),");
25         Sequence list =new Sequence(number);
26         //插入罪犯的名字,以A B C D为例
27         for (int i = 0; i < number; i++) {
28             list.insert(i,(char)('A'+i)+"");
29         }
30         //输出之前输入的罪犯名字,查看是否正确
31         list.display();
32         //计算起始位置
33         int i=start;
34         //找差别distance距离的元素或罪犯
35         while (list.length()>1) {
36             //处决间隔distance的元素或罪犯
37             i=(i+distance-1)%list.length();
38             System.out.print("删除"+list.remove(i).toString()+" ");
39             list.display();
40         }
41         System.out.println("被赦免者是"+list.get(0).toString());
42     }
43     
44     
45     
46 }
点击+展开代码

c.测试及结果分析

    

3.解法2:约瑟夫环的链表存储结构解法

a.链表Node节点定义

 1 package com.neusoft.chapter4.exercise;
 2 public class Node {
 3     public Object data;// 数据域
 4     public Node next;// 指针域
 5     public Node() { //构造空节点
 6         this(null,null);
 7     }
 8     public Node(Object data){//构造有一个参数的数据域
 9         this(data,null);
10     }
11     public Node(Object data,Node node){//构造数据域和指针域
12         this.data=data;
13         this.next=node;
14     }
15 }

展开代码可直接复制

 1 package com.neusoft.chapter4.exercise;
 2 public class Node {
 3     public Object data;// 数据域
 4     public Node next;// 指针域
 5     public Node() { //构造空节点
 6         this(null,null);
 7     }
 8     public Node(Object data){//构造有一个参数的数据域
 9         this(data,null);
10     }
11     public Node(Object data,Node node){//构造数据域和指针域
12         this.data=data;
13         this.next=node;
14     }
15 }
点击+复制代码

b.LinkList带头节点的单链表定义

  1 package com.neusoft.chapter4.exercise;
  2 /**
  3  * 带头结点的单链表
  4  */
  5 import java.util.Scanner;
  6 public class LinkedList  {
  7     public Node head;//链表的头指针
  8     public LinkedList() {
  9         head = new Node();//初始化头结点
 10     }
 11     public LinkedList(int n,boolean order){
 12         //如果order=1采用尾插法,如果order=2采用头插法
 13         this();
 14         if (order) {
 15             create1(n);
 16         }else {
 17             create2(n);
 18         }
 19     }
 20     private void create1(int n) {
 21         //尾插法
 22         Scanner sc = new Scanner(System.in);
 23         for (int i = 0; i < n; i++) {
 24             insert(length(), sc.next());
 25         }
 26     }
 27     private void create2(int n) {
 28         //头插法
 29         Scanner sc = new Scanner(System.in);
 30         for (int i = 0; i < n; i++) {
 31             insert(0, sc.next());
 32         }
 33     }
 34 
 35     public int length() {
 36         // 链表的长度
 37         Node p = head.next;
 38         int length=0;
 39         while (p!=null) {
 40             p=p.next; //指向后继节点
 41             length++;
 42         }
 43         return length;
 44     }
 45 
 46     public Object get(int i) {
 47         // 读取链表中第i个节点
 48         Node p = head.next;
 49         int j=0;
 50         if (j>i||p==null) {
 51             System.out.println("第"+i+"个元素不存在");
 52         }
 53         while (p!=null&&j<i) {//从头结点开始查找,找到第i各节点或者p的指针域为空停止
 54             p=p.next;
 55             j++;
 56         }
 57         return p.data;
 58     }
 59 
 60     public void insert(int i, Object x) {
 61         // 在第i个节点之前插入一个值为x的新节点
 62         Node p = head;
 63         int j=-1;
 64         while (p!=null &&j<i-1) {
 65             p=p.next;
 66             j++;
 67         }
 68         if (j>i-1||p==null) {
 69             System.out.println("插入位置不合法");
 70         }
 71         Node s = new Node(x);//新开辟的s节点
 72         //从链表中间或表尾进行插入
 73         s.next=p.next;
 74         p.next=s;
 75     }
 76 
 77     public Object remove(int i) {
 78         // 删除单链表的第i个节点
 79         Node p = head;
 80         int j=-1;
 81         while (p.next!=null&&j<i-1) {
 82             p=p.next;
 83             j++;
 84         }
 85         String old=(String)p.next.data;//保存要删除的值
 86         if (j>i-1||p.next==null) {
 87             System.out.println("删除位置不合法");
 88         }
 89         p.next=p.next.next;
 90         return old;
 91     }
 92 
 93     public int indexOf(Object x) {
 94         // 查找值为x的位置
 95         Node p = head.next;
 96         int j=0;
 97         while (p!=null&&!p.data.equals(x)) {
 98             p= p.next;
 99             j++;
100         }
101         if (p!=null) {
102             return  j;
103         }else {
104             return -1;
105         }
106     }
107 
108     public void display() {
109         // 输出单链表的所有节点
110         Node node = head.next;
111         while(node !=null){
112             System.out.print(node.data+" ");
113             node=node.next;
114         }
115         System.out.println();
116     }
117 }

展开代码可直接复制

  1 package com.neusoft.chapter4.exercise;
  2 /**
  3  * 带头结点的单链表
  4  */
  5 import java.util.Scanner;
  6 public class LinkedList  {
  7     public Node head;//链表的头指针
  8     public LinkedList() {
  9         head = new Node();//初始化头结点
 10     }
 11     public LinkedList(int n,boolean order){
 12         //如果order=1采用尾插法,如果order=2采用头插法
 13         this();
 14         if (order) {
 15             create1(n);
 16         }else {
 17             create2(n);
 18         }
 19     }
 20     private void create1(int n) {
 21         //尾插法
 22         Scanner sc = new Scanner(System.in);
 23         for (int i = 0; i < n; i++) {
 24             insert(length(), sc.next());
 25         }
 26     }
 27     private void create2(int n) {
 28         //头插法
 29         Scanner sc = new Scanner(System.in);
 30         for (int i = 0; i < n; i++) {
 31             insert(0, sc.next());
 32         }
 33     }
 34 
 35     public int length() {
 36         // 链表的长度
 37         Node p = head.next;
 38         int length=0;
 39         while (p!=null) {
 40             p=p.next; //指向后继节点
 41             length++;
 42         }
 43         return length;
 44     }
 45 
 46     public Object get(int i) {
 47         // 读取链表中第i个节点
 48         Node p = head.next;
 49         int j=0;
 50         if (j>i||p==null) {
 51             System.out.println("第"+i+"个元素不存在");
 52         }
 53         while (p!=null&&j<i) {//从头结点开始查找,找到第i各节点或者p的指针域为空停止
 54             p=p.next;
 55             j++;
 56         }
 57         return p.data;
 58     }
 59 
 60     public void insert(int i, Object x) {
 61         // 在第i个节点之前插入一个值为x的新节点
 62         Node p = head;
 63         int j=-1;
 64         while (p!=null &&j<i-1) {
 65             p=p.next;
 66             j++;
 67         }
 68         if (j>i-1||p==null) {
 69             System.out.println("插入位置不合法");
 70         }
 71         Node s = new Node(x);//新开辟的s节点
 72         //从链表中间或表尾进行插入
 73         s.next=p.next;
 74         p.next=s;
 75     }
 76 
 77     public Object remove(int i) {
 78         // 删除单链表的第i个节点
 79         Node p = head;
 80         int j=-1;
 81         while (p.next!=null&&j<i-1) {
 82             p=p.next;
 83             j++;
 84         }
 85         String old=(String)p.next.data;//保存要删除的值
 86         if (j>i-1||p.next==null) {
 87             System.out.println("删除位置不合法");
 88         }
 89         p.next=p.next.next;
 90         return old;
 91     }
 92 
 93     public int indexOf(Object x) {
 94         // 查找值为x的位置
 95         Node p = head.next;
 96         int j=0;
 97         while (p!=null&&!p.data.equals(x)) {
 98             p= p.next;
 99             j++;
100         }
101         if (p!=null) {
102             return  j;
103         }else {
104             return -1;
105         }
106     }
107 
108     public void display() {
109         // 输出单链表的所有节点
110         Node node = head.next;
111         while(node !=null){
112             System.out.print(node.data+" ");
113             node=node.next;
114         }
115         System.out.println();
116     }
117 }
点击+展开代码

c.约瑟夫问题代码组织

 1 package com.neusoft.chapter4.exercise;
 2 /**
 3  * @author zhao-chj
 4  * 古代判官要判决number个罪犯的死刑,制定了一条荒谬的法律
 5  *   将犯人站成一个圈,从start开始数起,每数到第distance
 6  * 个就处决他,依照此规律直到最后剩下一个人赦免。
 7  *   如当number=5时候,start=0,distance=2时:
 8  *   1.假设五个人是A B C D E
 9  *   2.从A开始每隔两个处决一个人,依次处决
10  *   3.原始序列A(0) B(1) C(2) D(3) E(4)
11  *      第一次A(0) C(2) D(3) E(4)  干掉B(1),从c开始
12  *      第二次A(0) C(2) D(3) E(4)  干掉D(3),从e开始
13  *      第三次A(0) C(2) E(4)  干掉A(0),从c开始数
14  *      第四次C(2) E(4)  干掉E(4)
15  *      第五次C(2)   c是被赦免的人
16  */
17 public class Josephus_LinkList {
18     public static void main(String[] args) {
19         new Josephus_LinkList(5, 0, 2);
20         System.out.println("**********************");
21         new Josephus_LinkList(10, 0, 1);
22     }
23     public Josephus_LinkList(int number,int start,int distance) {
24         // TODO 和类名相同的方法就是构造函数,是用于初始化变量的
25         System.out.println
26         ("Josephus("+number+","+start+","+distance+"),");
27         //插入罪犯的名字,以A B C D为例
28         System.out.println("请您收入"+number+"个罪犯");
29         //采用头插法输入各个元素
30         LinkedList list =new LinkedList(number,true);
31         //输出之前输入的罪犯名字,查看是否正确
32         list.display();
33         //计算起始位置
34         int i=start;
35         //找差别distance距离的元素或罪犯
36         while (list.length()>1) {
37             //处决间隔distance的元素或罪犯
38             i=(i+distance-1)%list.length();
39             System.out.print("删除"+list.remove(i).toString()+": ");
40             list.display();
41         }
42         System.out.println("被赦免者是"+list.get(0).toString());//get(0)是获得元素
43     }
44     
45     
46     
47 }

展开并复制代码

 1 package com.neusoft.chapter4.exercise;
 2 /**
 3  * @author zhao-chj
 4  * 古代判官要判决number个罪犯的死刑,制定了一条荒谬的法律
 5  *   将犯人站成一个圈,从start开始数起,每数到第distance
 6  * 个就处决他,依照此规律直到最后剩下一个人赦免。
 7  *   如当number=5时候,start=0,distance=2时:
 8  *   1.假设五个人是A B C D E
 9  *   2.从A开始每隔两个处决一个人,依次处决
10  *   3.原始序列A(0) B(1) C(2) D(3) E(4)
11  *      第一次A(0) C(2) D(3) E(4)  干掉B(1),从c开始
12  *      第二次A(0) C(2) D(3) E(4)  干掉D(3),从e开始
13  *      第三次A(0) C(2) E(4)  干掉A(0),从c开始数
14  *      第四次C(2) E(4)  干掉E(4)
15  *      第五次C(2)   c是被赦免的人
16  */
17 public class Josephus_LinkList {
18     public static void main(String[] args) {
19         new Josephus_LinkList(5, 0, 2);
20         System.out.println("**********************");
21         new Josephus_LinkList(10, 0, 1);
22     }
23     public Josephus_LinkList(int number,int start,int distance) {
24         // TODO 和类名相同的方法就是构造函数,是用于初始化变量的
25         System.out.println
26         ("Josephus("+number+","+start+","+distance+"),");
27         //插入罪犯的名字,以A B C D为例
28         System.out.println("请您收入"+number+"个罪犯");
29         //采用头插法输入各个元素
30         LinkedList list =new LinkedList(number,true);
31         //输出之前输入的罪犯名字,查看是否正确
32         list.display();
33         //计算起始位置
34         int i=start;
35         //找差别distance距离的元素或罪犯
36         while (list.length()>1) {
37             //处决间隔distance的元素或罪犯
38             i=(i+distance-1)%list.length();
39             System.out.print("删除"+list.remove(i).toString()+": ");
40             list.display();
41         }
42         System.out.println("被赦免者是"+list.get(0).toString());//get(0)是获得元素
43     }
44     
45     
46     
47 }
点击+展开代码

e.测试结果

   

 

posted @ 2017-03-23 19:44  CJZhaoSimons  阅读(886)  评论(0编辑  收藏  举报