循环链表
最近开始复习数据结构,今天手写了一个约瑟夫循环问题。
什么是循环链表
首尾相连的链表:head->last=tail;tail->next=head
建立循环链表和建立普通链表方法差不多,只需要首尾相连即可
约瑟夫循环问题
已知 n 个人(以编号1,2,3,…,n分别表示)围坐在一张圆桌周围,从编号为 k 的人开始顺时针报数,数到 m 的那个人出列;他的下一个人又从 1 还是顺时针开始报数,数到 m 的那个人又出列;依次重复下去,要求找到最后出列的那个人。
例如:5个人,编号依次为12345,从第3个人开始报数,报到2的退出,然后下一个接着从开始报数
那么退出的顺序是:4-1-3-2-5
循环链表解决约瑟夫循环问题
思路:从第k个节点开始,将第m-1个节点释放,连接好链表即可。
C++实现
#include<iostream>
#include<cstdlib>
using namespace std;
#include<string>
struct list {
struct list* next;
struct list* last;
int data;//编号
};
struct list* creat(int n)//创建循环链表
{
struct list* head,*tail,*normal;
head = new list;
tail = new list;
head = tail;//不需要这一句
cout << "请输入数据" << endl;//头结点的数据
cin >> head->data;
for (int i = 1; i < n; i++)
{
normal = new list;
cout << "请输入数据" << endl;
cin >> normal->data;
tail->next = normal;//尾节点连接新创建的节点
normal->last = tail;//新创建的节点的上一个是尾节点
tail = normal;//将尾节点移动到新创建的节点
}
head->last = tail;//首尾相连
tail->next = head;//首尾相连
return head;
}
void delPerson(struct list* p) {//功能函数
struct list* head, * tail;//不需要用到head,后面的head都可以省去
head = new list;
tail = new list;
head = p;
int k;
cout << "请输入K" << endl;
cin >> k;
while (p->data != k)//从第k个人开始报数
{
tail = p;
p = p->next;
}
cout << "请输入m" << endl;
int m;
int i = 0;
cin >> m;
while (tail->next != tail)//如果不是只剩最后一个节点
{
for (i = 0; i < m-1; i++)
{
tail = p;
p = p->next;
}
tail->next = p->next;//tail的next连接p的next
p->next->last = tail;//p的下一个的上一个是tail
cout << "删除的编号是:" << p->data << endl;
free(p);//释放p
p = tail->next;//p移动到tail的next
}
cout << "删除的编号是:" << tail->data<<"\n";
}
int main()
{
struct list* p;
p = new list;
int n;
cout << "请输入总人数" << endl;
cin >> n;
p = creat(n);
delPerson(p);
system("pause");
return 0;
}