C语言实现约瑟夫环问题:循环链表解法及代码优化
这段代码实现约瑟夫环问题,使用循环链表结构,但存在两个问题:
-
在
create_linked_list函数中,循环链表的最后一个节点的next指针没有正确指向头节点。需要在循环结束后加上tail->next = head;。 -
在
delete_node函数中,应该先将current节点从链表中断开,再释放其内存,然后再将prev节点的next指针指向current->next。所以需要将free(current);的位置放到prev->next = current->next;之前。
除了这两个问题,代码的逻辑和功能似乎是正确的。以下是修正后的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME_SIZE 50
typedef struct Node {
int id;
char name[NAME_SIZE];
char gender;
int age;
struct Node* next;
} Node;
Node* create_linked_list(int n) {
Node* head = (Node*)malloc(sizeof(Node));
head->next = head;
Node* tail = head;
for (int i = 0; i < n; i++) {
Node* new_node = (Node*)malloc(sizeof(Node));
printf("请输入第%d个人的编号、姓名、性别和年龄:", i + 1);
scanf("%d %s %c %d", &new_node->id, new_node->name, &new_node->gender, &new_node->age);
new_node->next = head;
tail->next = new_node;
tail = new_node;
}
// 将最后一个节点的next指针指向头节点,形成循环链表
tail->next = head;
return head;
}
void print_linked_list(Node* head) {
Node* current = head->next;
while (current != head) {
printf("%d %s %c %d\n", current->id, current->name, current->gender, current->age);
current = current->next;
}
}
void delete_node(Node* prev, Node* current) {
prev->next = current->next;
free(current);
}
void josephus_circle(Node* head, int start_id, int interval, int remaining) {
Node* current = head->next;
Node* prev = head;
while (current->id != start_id) {
prev = current;
current = current->next;
}
while (remaining > 0) {
for (int i = 1; i < interval; i++) {
prev = current;
current = current->next;
}
printf("出列的人的编号是:%d\n", current->id);
Node* next = current->next;
delete_node(prev, current);
current = next;
remaining--;
}
printf("最后剩余的人的编号、姓名、性别和年龄是:%d %s %c %d\n", current->id, current->name, current->gender, current->age);
}
int main() {
int n;
printf("请输入人数:");
scanf("%d", &n);
Node* head = create_linked_list(n);
print_linked_list(head);
int start_id, interval, remaining;
printf("请输入开始报数的人的编号、间隔的个数和剩余人数:");
scanf("%d %d %d", &start_id, &interval, &remaining);
josephus_circle(head, start_id, interval, remaining);
return 0;
}
用例:
- **人数:**5,**开始报数:**1,**间隔:**2,**剩余人数:**1
- **人数:**7,**开始报数:**3,**间隔:**3,**剩余人数:**1
- **人数:**10,**开始报数:**5,**间隔:**4,**剩余人数:**1
- **人数:**15,**开始报数:**8,**间隔:**5,**剩余人数:**1
- **人数:**20,**开始报数:**12,**间隔:**6,**剩余人数:**1
- **人数:**25,**开始报数:**17,**间隔:**7,**剩余人数:**1
- **人数:**30,**开始报数:**22,**间隔:**8,**剩余人数:**1
- **人数:**35,**开始报数:**27,**间隔:**9,**剩余人数:**1
- **人数:**40,**开始报数:**32,**间隔:**10,**剩余人数:**1
- **人数:**45,**开始报数:**37,**间隔:**11,**剩余人数:**1
- **人数:**50,**开始报数:**42,**间隔:**12,**剩余人数:**1
- **人数:**5,**开始报数:**1,**间隔:**3,**剩余人数:**2
- **人数:**7,**开始报数:**3,**间隔:**4,**剩余人数:**2
- **人数:**10,**开始报数:**5,**间隔:**5,**剩余人数:**2
- **人数:**15,**开始报数:**8,**间隔:**6,**剩余人数:**2
- **人数:**20,**开始报数:**12,**间隔:**7,**剩余人数:**2
- **人数:**25,**开始报数:**17,**间隔:**8,**剩余人数:**2
- **人数:**30,**开始报数:**22,**间隔:**9,**剩余人数:**2
- **人数:**35,**开始报数:**27,**间隔:**10,**剩余人数:**2
- **人数:**40,**开始报数:**32,**间隔:**11,**剩余人数:**2
- **人数:**45,**开始报数:**37,**间隔:**12,**剩余人数:**2
- **人数:**5,**开始报数:**1,**间隔:**2,**剩余人数:**3
- **人数:**7,**开始报数:**3,**间隔:**3,**剩余人数:**3
- **人数:**10,**开始报数:**5,**间隔:**4,**剩余人数:**3
- **人数:**15,**开始报数:**8,**间隔:**5,**剩余人数:**3
- **人数:**20,**开始报数:**12,**间隔:**6,**剩余人数:**3
- **人数:**25,**开始报数:**17,**间隔:**7,**剩余人数:**3
- **人数:**30,**开始报数:**22,**间隔:**8,**剩余人数:**3
- **人数:**35,**开始报数:**27,**间隔:**9,**剩余人数:**3
- **人数:**40,**开始报数:**32,**间隔:**10,**剩余人数:**3
- **人数:**45,**开始报数:**37,**间隔:**11,**剩余人数:**3
- **人数:**5,**开始报数:**1,**间隔:**2,**剩余人数:**4
- **人数:**7,**开始报数:**3,**间隔:**3,**剩余人数:**4
- **人数:**10,**开始报数:**5,**间隔:**4,**剩余人数:**4
- **人数:**15,**开始报数:**8,**间隔:**5,**剩余人数:**4
以上用例涵盖了不同人数、开始报数、间隔和剩余人数的情况,可以全面测试代码的正确性。
原文地址: https://www.cveoy.top/t/topic/O0z 著作权归作者所有。请勿转载和采集!