代码:
#include <iostream>
using namespace std;
struct node {
int id;
node *next;
};
int len=0; //存现在链表的长度
int main()
{
node*head,*temp,*tail;
head=new node;
head->next= head;
tail=head;
int A,B;
cin>>A>>B;
len=A;
int num=1;
while(A--) //创建循环单链表
{
temp = new node;
temp->id = num;
temp->next = head;
tail->next = temp;
tail = temp;
num++;
}
temp=head;
while(1)
{
for(int i=0;i<B-1;i++) //循环B-1次,找要删除结点的前驱。
{
temp=temp->next;
if(temp==head)//如果到头结点则跳过(循环多一次就行),因为前驱应该是有数值的结点。
{
i--;
}
}
node *q=temp->next; //待删除的结点。
if(q==head)//如果待删除的结点是头结点,则跳过,实际应该是下一个有数值的结点。
{
q=head->next;
temp=head; //让temp重新回到头结点,因为该从头开始循环(即数1的是现在链表中第一个有数值的结点)。
}
temp->next=q->next; //删除结点
delete q;
len--;
if(len==2)
{
break; //剩下两个时跳出
}
}
for(temp=head->next;temp!=head;temp=temp->next)
{
cout<<temp->id<<" \n"[temp->next==head];//数组索引表达式
}
return 0;
}
参考:
循环单链表解决约瑟夫问题
数组索引表达式
在C++中,表达式 " \n"[temp->next==head]
是一种利用数组的索引来选择字符的技巧性写法。这里发生了以下几件事情:
" \n"
是一个字符串字面量,它包含了一个空格字符和一个换行符。temp->next == head
是一个比较表达式,它比较两个指针是否相等。- 如果
temp->next == head
为真(即指针相等),则表达式的结果为1(因为C++中布尔真值true会被转换为整数1),如果为假,则结果为0。 - 这个整数结果(0或1)被用作字符串
" \n"
的索引。
因此,如果temp->next
指向head
,则表达式的结果是换行符\n
;如果temp->next
不指向head
,则结果是字符串的第一个字符,即空格' '
。
这种写法虽然看起来很简洁,但可读性不佳,通常不推荐使用,因为它可能会让代码难以理解。这种技巧性写法在需要非常紧凑的代码时可能会出现,但在大多数情况下,使用普通的if-else语句或条件运算符(?:
)来选择字符会更加清晰。例如:
char result = (temp->next == head) ? '\n' : ' ';
这样的写法更容易让人理解意图。