一群猴子要选新猴王。新猴王的选择方法是:让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。请问是原来第几号猴子当选猴王?
输入格式:
输入在一行中给一个正整数N(≤1000)。
输出格式:
在一行中输出当选猴王的编号。
输入样例:
11
输出样例:
7
//7-28 猴子选大王
#include <stdio.h>
#include <iostream>
using namespace std;
//创建节点对象,包含next指针,和该节点存储的数据
class Node{
public:
Node* next;
int data;
int index;
};
//创建单循环链表对象,其中头结点和该链表的长度均为私有
class circlelist{
private:
Node* head;
int length;
public:
//链表初始化
circlelist(){
head = new Node();
head->next = head;
head->data = 0;
length = 0;
}
//析构函数
~circlelist(){
delete (head);
}
void createCircleList(int n);//创建单向循环链表
void traverseNode();//遍历链表
void deleteNode(int n);//删除位置n的节点
void insertNode(int n, int data);//在位置n上插入int类型的data
int getLength();//获取链表的长度
bool isEmpty();//判断链表是否为空
Node* returnHeadNode();//返回头结点
};
//新建一个长度为n的单循环链表
void circlelist::createCircleList(int n) {
if (n < 0){
cout<<"Wrong Length!\n";
} else{
//链表的长度设置为n
length = n;
//cout<<"Input the data:\n";
//新建两个节点,其中之一为头结点
Node *p,*q;
p = head;
int i = 1;
while (n--){
//从头结点开始,首先新建一个节点
q = new Node();
q->data = i;
//输入该节点存储的数据
//cin>>q->data;
//将头结点的next指针置为该新建的节点
p->next = q;
//该节点的next指针置为头结点
q->next = head;
//将新建的节点作为下一次连接的前驱节点
p = q;
//该节点对应的index即为i
p->index = i;
i++;
}
}
}
//遍历该单循环链表
void circlelist::traverseNode() {
Node *p;
p = head->next;
while (p!=head){
//测试输出
cout<<"Index "<<p->index<<":"<<p->data<<"\n";
// cout<<p->data<<" ";
p = p->next;
}
// cout<<"\n";
}
//删除位置n上的节点
void circlelist::deleteNode(int n) {
if (n < 0 || n > length){
cout<<"Wrong Position!\n";
return;;
} else{
Node *p,*q;
p = head;
for (int i = 1; i < n; ++i) {
p = p->next;
}
//找到位置n的节点,赋值于q
q = p->next;
//重点是要处理前后的链接关系
p->next = q->next;
//删除位置n节点之后,后面所有节点的index全部都要减去1
Node *temp;
temp = p->next;
while (temp != head){
temp->index--;
temp = temp->next;
}
//删除该节点
delete q;
q = NULL;
}
}
//在位置n上插入数据data
void circlelist::insertNode(int n, int data) {
Node *p,*q;
p->data = data;
q = head;
for (int i = 1; i < n; ++i) {
q = q->next;
}
p->next = q->next;
q->next = p;
}
//我知道哪里出问题了,是因为getlength的时候返回的是设定的length
//而且评判的时候判断的标准也是用的getlength返回的值
//但是删除操作之后,整个链表的长度是会发生改变的,所以这里是错的。
//获取该单循环链表的长度
int circlelist::getLength() {
Node *p;
int length = 0;
p = head;
do{
p = p->next;
length++;
}while (p->next != head);
return length;
}
//判断该单循环链表是否为空
bool circlelist::isEmpty() {
return head==head->next;
}
//返回头结点
Node* circlelist::returnHeadNode() {
return head;
}
int main(){
int n = 0;
cin>>n;
if (n > 1000 || n < 0){
return 0;
}
circlelist clist;
clist.createCircleList(n);
//现在创建了一个单链表,且单链表中
// clist.traverseNode();
/*int length = clist.getLength();
cout<<"Length of Cyclelist is:"<<length<<"\n";*/
// clist.deleteNode(3);
// cout<<"----------\n";
// clist.traverseNode();
//测试返回单循环链表的头结点
Node *head = clist.returnHeadNode();
// cout<<head->next->index;
//从头结点的下一个节点开始计算
Node *p = head->next;
/* //打印所有节点对应index及其data
for (int i = 1; i <= n ; ++i) {
cout<<"Index "<<p->index<<":"<<p->data<<"\n";
p = p->next;
}*/
//此时执行完之后p为空节点,p->next->index = 1
//cout<<p->next->index<<"\n";
// cout<<p->index<<"\n";
// cout<<p->next->index<<"\n";
// p = p->next->next;
int A[n];
int i = 0,tmp = 0;
//找到其中要被删掉的节点的index,并存储在数组A中
// cout<<clist.getLength()<<"\n";
int count = 0;
int round = 0;
cout<<"Original Clist:\n";
clist.traverseNode();
cout<<"\n";
do{
tmp = i;
round ++;
for (int k = 1; k <= clist.getLength() ; ++k) {
if ((p->index + count)%3==0){
A[i] = p->index;
i++;
}
p = p->next;
}
//如果在这里设置p=p->next,将会出错
//因为加入删掉最后一个节点,则就会使得p=p->next->next,就是越过第一个节点开始往后计算
//从而出现错误,这里卡了好久。
//所以应该是所有要删除的节点都已经删掉之后
//再把p设置为p->next,此时才指向第一个节点
//此时p指向第一个节点
cout<<"需要删除的索引位置:\n";
for (int j = 0; j < i; ++j) {
cout<<A[j]<<" ";
}
int length = clist.getLength();
cout<<"\n----After round"<<round<<" delete----\n";
//这里倒序删除,正向删除会因为前面先删除之后index也更新,删除的就是当删除的后面的值
for (int j = i - 1; j >= tmp; --j) {
clist.deleteNode(A[j]);
}
//此时p为头结点,p->index = 0
//所以才会把0写进A中
p = p->next;
clist.traverseNode();
cout<<"The length of Clist is:"<<clist.getLength()<<"\n";
// count = clist.getLength() % 3;
// cout<<p->data<<"\n";
count = (count + length) % 3;
cout<<"count:"<<count<<"\n\n";
}while (clist.getLength()!=1);
return 0;
}
诸以记之,与君共勉~