前天学了循环链表,一直再没管,今天来应用一下,感觉自己写麻烦了…
循环链表与单链表的区别就在于表尾指针不是NULL,而是等于first。这就产生了一个好处就是可以从任何节点开始访问到所有节点。
代码
#include<iostream>
using namespace std;
struct People
{
int data;
People* link=NULL;
};
class Josephus
{
private:
People* first;
int n;
public:
Josephus(int n=0,People* first = NULL):n(n){}
~Josephus() { makeEmpty(); };
void makeEmpty();
int run(int m);
void create();
void show();
};
void Josephus::show()
{
People* p = first;
int nn = n;
while (nn--)
{
cout << p->data << endl;
p = p->link;
}
}
void Josephus::makeEmpty()
{
while (n--)
{
People* p = first->link;
first->link = p->link;
delete p;
}
first = NULL;
}
void Josephus::create()
{
first = new People{ 1 };
People* p = first;
int i = 2;
while (i <= n)
{
People* t = new People{i};
p->link = t;
p = p->link;
i++;
}
p->link = first; //循环
}
int Josephus::run(int m)
{
if (n == 1)
return 1;
int i = 1;
People* p = first;
while (n != 1)
{
if (i % m == m-1)
{
People* t = p->link;
p->link = t->link;
delete t;
i++;
n--;
}
p = p->link;
i++;
}
first = p;
return first->data;
}
int main()
{
int n, m,luckyOne;
cin >> n >> m;
Josephus j = Josephus(n);
j.create();
luckyOne = j.run(m);
cout << luckyOne << endl;
return 0;
}
后记
看了看数据结构树上的思路,发现也很清晰,就是执行n-1趟(每次出一个人,最后剩一个人),每趟到m-1就出来删除第m个。
int Josephus::run(int m)
{
if (n == 1)
return 1;
People* p = first;
int j;
int nn = n;
for (int i = 1; i <= nn - 1; i++)
{
for (j = 1; j < m-1; j++)
{
p = p->link;
}
People* del = p->link;
p->link = del->link;
cout << del->data << endl;
delete del;
n--;
p = p->link;
}
first = p;
return p->data;
}
忘记n–导致NULL问题。。。。