分别用顺序表、循环链表完成约瑟夫问题
时间: 2023-04-26 11:01:57 浏览: 128
约瑟夫问题是一个经典的数学问题,描述如下:n个人围成一圈,从第一个人开始报数,数到m的人出圈,剩下的人继续从1开始报数,数到m的人再出圈,直到所有人出圈。现在我们分别用顺序表和循环链表来实现这个问题。
1. 顺序表实现约瑟夫问题
顺序表是一种线性结构,可以用数组来实现。我们可以用一个数组来表示n个人,每个人的编号为1~n。然后我们按照题目要求,从第一个人开始报数,数到m的人出圈,直到所有人出圈。具体实现如下:
1)创建一个长度为n的数组,用来表示n个人。
2)设置一个指针p,指向数组的第一个元素。
3)从1开始循环,每次循环数到m的人出圈,直到所有人出圈。
4)每次循环时,先将p向后移动m-1个位置,然后将p指向的元素删除,即将p后面的元素向前移动一个位置。
5)如果p指向的是最后一个元素,那么将p指向数组的第一个元素。
6)重复步骤3~5,直到所有人出圈。
2. 循环链表实现约瑟夫问题
循环链表是一种链式结
相关问题
用循环链表实现约瑟夫问题
约瑟夫问题是一个经典的算法问题,假设有n个人围成一圈,编号从1到n,从第1个人开始报数,报到第m个人出列,然后从出列的下一个人开始重新报数,直到所有人都出列为止。请使用循环链表实现这个算法。
首先,我们需要定义一个节点类,表示每个人的信息和位置。节点类包含两个属性,一个是编号,另一个是指向下一个节点的指针。
```python
class Node:
def __init__(self, data):
self.data = data
self.next = None
```
然后,我们需要构造循环链表,将所有人的信息存储在链表中。为了方便起见,我们可以先构造一个单向链表,然后将链表的尾节点指向头节点,形成一个循环链表。
```python
def construct_circle_list(n):
head = Node(1)
cur = head
for i in range(2, n+1):
new_node = Node(i)
cur.next = new_node
cur = new_node
cur.next = head
return head
```
接下来,我们需要实现约瑟夫问题的解法。我们可以使用一个计数器count,表示当前报数的人的位置,当count等于m时,将该节点从链表中删除。具体实现如下:
```python
def josephus(head, m):
cur = head
while cur.next != cur:
count = 1
while count < m-1:
cur = cur.next
count += 1
print("出列的人的编号为:", cur.next.data)
cur.next = cur.next.next
cur = cur.next
print("出列的人的编号为:", cur.data)
```
最后,我们可以在主函数中调用上述函数,解决约瑟夫问题。
```python
if __name__ == '__main__':
n = 10
m = 3
head = construct_circle_list(n)
josephus(head, m)
```
上述代码的输出结果为:
```
出列的人的编号为: 3
出列的人的编号为: 6
出列的人的编号为: 9
出列的人的编号为: 2
出列的人的编号为: 7
出列的人的编号为: 1
出列的人的编号为: 8
出列的人的编号为: 5
出列的人的编号为: 10
出列的人的编号为: 4
```
这个结果符合我们的预期,表示最后出列的顺序为3、6、9、2、7、1、8、5、10、4。
用头插法建立循环链表解决约瑟夫问题
约瑟夫问题是一个经典的数学问题,假设有n个人围成一圈,从第一个人开始报数,数到m的人出圈,然后从出圈的人的下一个人开始重新报数,数到m的人再次出圈,直到所有人都出圈为止。现在我们可以用头插法建立循环链表来解决这个问题。
首先,我们可以用一个循环链表来表示这n个人。我们可以把每个人看作一个节点,节点中保存着这个人的编号和指向下一个节点的指针。
接下来,我们可以用头插法建立这个循环链表。具体地,我们可以从最后一个人开始,一个一个地向链表中插入节点。每次插入一个节点,我们都把它插入到链表的头部,也就是让它成为链表的第一个节点。这样,最后形成的循环链表就是按照从最后一个人到第一个人的顺序排列的。
最后,我们可以采用模拟的方式来解决约瑟夫问题。我们从链表的第一个节点开始,每次数m个节点,然后把这个节点从链表中删除。然后,我们再从被删除节点的下一个节点开始继续数m个节点,直到所有节点都被删除为止。
下面是用C++代码实现头插法建立循环链表解决约瑟夫问题的示例:
```c++
#include <iostream>
using namespace std;
// 定义节点
struct Node {
int data; // 保存节点数据
Node* next; // 指向下一个节点的指针
};
// 头插法建立循环链表
Node* createCircularLinkedList(int n) {
Node* head = nullptr; // 链表头节点
for (int i = n; i > 0; i--) { // 从最后一个节点开始插入
Node* node = new Node(); // 创建新节点
node->data = i; // 设置新节点的数据
node->next = head; // 把新节点插入到头部
head = node; // 更新头节点
}
// 链表头尾相连,形成循环链表
Node* tail = head;
while (tail->next != nullptr) {
tail = tail->next;
}
tail->next = head;
return head;
}
// 解决约瑟夫问题
void josephus(int n, int m) {
Node* head = createCircularLinkedList(n); // 创建循环链表
Node* p = head; // 指向当前节点
while (n-- > 0) {
for (int i = 1; i < m; i++) { // 数m个节点
p = p->next;
}
cout << p->data << " "; // 输出出圈节点的数据
Node* q = p->next; // 保存下一个节点的指针
*p = *q; // 把下一个节点的数据复制到当前节点
delete q; // 删除下一个节点
}
cout << endl;
}
int main() {
int n = 8;
int m = 3;
josephus(n, m);
return 0;
}
```