第二次作业:
习题2 载具杀手与时停高手(约瑟夫环问题)
著名绅士简尚夫有一项特殊的天赋,他可以摧毁任意一辆载具(载具杀手)。他的朋友狄傲可以将时间暂停(时停高手)。他俩玩一个游戏。
有N辆车,编号1~N。其中编号A的是狄傲心爱的压路机。指定编号B的车作为起点,简尚夫首先摧毁这辆车;然后往后数K辆车,摧毁第K辆;然往后数K辆车,摧毁第K辆。数到最后一辆车,则回到剩余的第一辆车接着数。直到把所有车全部摧毁。当简尚夫将要摧毁狄傲的压路机时,狄傲会发动时停技能阻止他。
请你构建循环链表,模拟这个过程(模拟到发动时停技能时为止)。
最后按顺序打印时停技能发动时,剩下的车的编号。
输入:四个整数,空格隔开。
N : 车的数目。
A : 压路机的编号。
B : 作为起点的车的编号。
K : 每次跳过的车的数目。
输出:若干整数,空格隔开。
剩下的车的编号。
示例:
(输入)5 2 3 2
(输出)1 2 4
(说明)
初始:1->2->3->4->5->
摧毁第一辆车后:1->2->4->5->
摧毁第二辆车后:1->2->4->
下一辆要摧毁的车狄傲的压路机,于是他发动了时停,游戏结束。输出:1 2 4
循环链表节点类型定义(供参考):
struct ListNode {
int val;
ListNode *next;
};
刚开始总体骨架的构造出现问题,经过研究与提问,得到了最终的答案:
csdn版(有代码):
C循环链表程序出现Process returned -1073741819 (0xC0000005)的问题-编程语言-CSDN问答https://ask.csdn.net/questions/7521382?spm=1005.2025.3001.5141&weChatOA=StackOverflow版(原汁原味):
可是随后,我发现貌似使用结构体数组并没有什么意义,本来是为了好找每个结点,但是要是按照我在函数内部定义数组,那么由于 a[] 是一个自动变量(局部变量),我在外面仍然调用不了里面的 a[i] 的结点,因此我选择普通的结点,
但是要使用 *head 以及 *tail 来表示循环链表的头尾位置,这样,
(1)我们使用 *head 便于从头部向尾部进行遍历每个结点
(2)我们使用 *tail 便于进行尾插法的操作 *****
注:普通链表的头插法需要头指针,尾插法需要尾指针。
接下来:
在编程的过程中,出现了最大的问题就是:
在if判断条件的书写时,把比较是否相等的 == 当作了 =
于是,调了好长时间,终于在人眼 debug 的时候发现了
另外,告诉我一个道理,充分的运动有利于 bug 的寻找。
以下是目前的代码,
实现了基本的功能,但是在车车的总数为1的时候,程序会报错(如输入"1 1 1 1")。
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode
{
int val;
struct ListNode* next;
} ListNode;
///*
//makenode:
//input: *p(last node), val
//*/
//ListNode* makenode(ListNode* p, int value)
//{
// ListNode* new_node = (ListNode*)malloc(sizeof(ListNode));
// p->next = new_node;
// new_node->val = value;
// new_node->next = NULL;
// return new_node;
//}
/*
makecycle:
input: **head, **tail, N, A
*/
void makecycle(ListNode** head_ref, ListNode** tail_ref, int N, int A)
{
int i;
ListNode* new_node = NULL;
(*head_ref)->val = 1;
(*head_ref)->next = NULL;
(*tail_ref) = (*head_ref);
for(i = 1; i < N; i++)
{
new_node = (ListNode*)malloc(sizeof(ListNode));
(*tail_ref)->next = new_node;
(*tail_ref)->val = i;
printf("%d->", (*tail_ref)->val);//test
(*tail_ref) = new_node;
new_node->next = NULL;
new_node->val = i+1;
}
printf("%d", (*tail_ref)->val);//test
new_node->next = (*head_ref);
printf("\n------------------------------\n");
}
/*
denode:
input: **head, **tail, N, A, B, K
*/
int denode(ListNode** head_ref, ListNode** tail_ref, int N, int A, int B, int K)
{
ListNode* p = (*head_ref);
ListNode* q = (*head_ref);
//ListNode* r = NULL;
int i, j;
//
if(B != 1)
{
for(i = 1; i < B-1; i++)
{
if(p != NULL) p = p->next;
}
}
else
{
p->next = (*head_ref);
}
//
for(i = 1; i < A; i++)
{
if(q != NULL) q = q->next;
}
//
for(;;)
{
//
if((p->next != NULL)&&(p->next != q)&&(p->next != (*head_ref)))
{
printf("the deleted node: %d\n", p->next->val);
p->next = p->next->next;
}
//
if(p->next == q)
{
return 0;
}
//
if(p->next == (*head_ref))
{
(*head_ref) = (*head_ref)->next;
printf("the deleted node: %d\n", p->next->val);
p->next = p->next->next;
}
//
for(j = 1; j < K; j++)
{
p = p->next;
}
}
}
int main()
{
int N, A, B, K;
printf("N : 车的数目。\nA : 压路机的编号。\nB : 作为起点的车的编号。\nK : 每次跳过的车的数目。\n");
ListNode* p = NULL;
//input
scanf_s("%d %d %d %d", &N, &A, &B, &K);
//head node, tail node
ListNode* head = (ListNode*)malloc(sizeof(ListNode));
ListNode* tail = (ListNode*)malloc(sizeof(ListNode));
//makecylce
makecycle(&head, &tail, N, A);
//denode
denode(&head, &tail, N, A, B, K);
//output
p = head;
do
{
printf("%d ", p->val);
p = p->next;
}
while(p != head);
}