3. 循环链表
(1)实现一个循环链表
#include <stdafx.h>
#include <iostream>
using namespace std;
struct CNode
{
int data;
CNode *next;
CNode(){data = 0; next = this;}
/*【注】这里默认构造函数不能再和下面的构造函数合并了,因为this只能用在非静态成员函数中,而下面的构造函数是通过成员初
始化列表来完成对象构造的,这是在编译器便完成了的,而this本身所指向的对象要到运行期才能明确下来,因此不能用this作为默
认参数以及在初始化列表中进行初始化。其实,二者是一个概念,因为构造函数在进入函数体前一定会进行初始化的,如果默认参数
有规定值,则用该值进行初始化,否则编译器进行默认的初始化,然后才进行函数体中赋值操作。*/
CNode(int _data, CNode *_next):data(_data), next(_next){}
};
int main()
{
CNode *head, *p, *newCNode;
head = new CNode;
p = head;
int i;
for(i=1; i<10; ++i)
{
newCNode = new CNode(i, head);//循环链表的特色
p->next = newCNode;
p = newCNode;
}
for(p=head, i=0; i<10; ++i, p=p->next)
cout << p->data << " ";
cout << endl;
}
(2)Josephus问题(约瑟夫问题)
已知n个人(以编号1,2,……,n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数(从1开始报数),数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
#include <stdafx.h>
#include <iostream>
using namespace std;
struct CNode
{
int data;
CNode *next;
CNode(){data = 0; next = this;}
CNode(int _data, CNode *_next):data(_data), next(_next){}
};
void Josephus(int n, int k, int m)
{
CNode *head, *currPtr, *prevPtr, *newCNode;
//第一步:建立Josephus问题对应的循环链表
head = new CNode;
/*开始时,不能使用head = new CNode(1, head);因为开始时head并没赋值,将一个没有值的指针传递给
构造函数的实参将会导致运行时错误(因为可以通过编译时期的类型检测这一关)*/
head->data = 1;
currPtr = head;
for(int i=2; i<=n; ++i)
{
newCNode = new CNode(i, head);
currPtr->next = newCNode;
currPtr = currPtr->next;
}
//【另】循环链表的删除和插入不涉及表首和表尾的特殊情况的考虑,因此,一般不会出现在试题中。
//第二步:查找第k个结点
currPtr = head;
for(int i=1; i<k; ++i)//k>=1,循环k-1次为的是找到第k个结点
{
//当m=1时,j=m-1=0,于是下面循环的子循环不执行,于是后面的程序便用到这里的prevPtr了。
prevPtr = currPtr;//不能缺少这条语句,否则m=1时运行失败!
currPtr = currPtr->next;//循环结束后currPtr指向第k个人
}
//第三点:删除结点
for(int i=1; i<=n; ++i)//n>=1,每次循环减少一个,一共需要n次循环
{
for(int j=1; j<m; ++j)//查找要被删除的结点:从~m共需前进m-1步
{
prevPtr = currPtr;
currPtr = currPtr->next;
}
prevPtr->next = currPtr->next;
cout << currPtr->data << " is deleted\n";
delete currPtr;
//prevPtr的位置不变,currPtr的位置更新为prevPtr的下一结点(其实也是原currPtr的下一结点)
currPtr = prevPtr->next;
}
}
int main()
{
Josephus(13, 4, 1);//m=1意味着从第k(这里为)个人开始,依次进行删除
return 0;
}