以下时最近学习链表时候碰到的一个问题。
问题中涉及到生成链表,遍历链表,中间断开链表重新连接等操作。
题目如下:
计算理工学院有 NN 个同学,围成了一个圆圈,每人被顺序地编了一个序号(分别为 1,2,3… n1,2,3…n),从编号为 KK 的人开始报 11,他之后(顺初始数字增长方向计算序号)的人报 22,以此类推,数到某一个数字 MM 的人出列。出列同学的下一个人又从 11 开始继续报数,数到某一个数字 MM 的人出列。不断重复这一过程,直到所有人都出列为止。
你需要根据同学人数 NN 和给出的 KK 和 MM 计算出同学的正确出列顺序。
解题如下:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} Node;
Node *circle_create(int n);
void count_off(Node *head, int n, int k, int m);
int main() {
int n, k, m;
scanf("%d%d%d", &n, &k, &m);
Node *head = circle_create(n);
count_off(head, n, k, m);
return 0;
}
Node *circle_create(int n) {
Node *temp, *new_node, *head;
int i;
// 创建第一个链表节点并加数据
temp = (Node *) malloc(sizeof(Node));
head = temp;
head->data = 1;
// 创建第 2 到第 n 个链表节点并加数据
for(i = 2; i <= n; i++) {
new_node = (Node *) malloc(sizeof(Node));
new_node->data = i;
temp->next = new_node;
temp = new_node;
}
// 最后一个节点指向头部构成循环链表
temp->next = head;
return head;
}
void count_off(Node *head, int n, int k, int m) {
Node *temp = head;
int zongshu = n;
int i;
//判断是从哪里开始
for (i = 1; i < k; i++) {
temp = temp->next;
}
//剩余2个节点之前一直循环
while(zongshu > 2) {
i = 0;
for (;;) {
i++;
if (i == m) {
//获取输出节点的前一个节点
Node *pretemp = temp;
while (pretemp->next != temp) {
pretemp = pretemp->next;
}
//将输出节点的前后两个节点串联起来
pretemp->next = temp->next;
//输出节点的data
printf("%d ", temp->data);
//更新下次开始的节点
temp = temp->next;
zongshu--;
break;
}
temp = temp->next;
}
}
if (m % 2 == 0) {
printf("%d ", temp->next->data);
printf("%d", temp->data);
}else {
printf("%d ", temp->data);
printf("%d", temp->next->data);
}
return;
}
除了以上的C代码实现之外,还有额外的C++代码实现。
问题如下:
有n个人(编号从1到n)站成一个还,从1号开始计数,每数到第m个人就让其退出,且从下一个人开始重新计数,依次进行下去,直到所有人都退出,最后退出者为胜者。
//
// Created by 王一飞 on 2020/9/5.
//
#include<iostream>
using std::cin;
using std::cout;
using std::endl;
template <typename Type> class Node {
public:
Type data;
Node<Type> *next;
Node(const Type &_data) {
data = _data;
next = NULL;
}
};
template <typename Type> class LinkedList {
private:
Node<Type> *head;
public:
LinkedList() {
head = NULL;
}
~LinkedList() {
if (head == NULL) {
return;
}
Node<Type> *current_node = head->next;
head->next = NULL;
while (current_node != NULL) {
Node<Type> *delete_node = current_node;
current_node = current_node->next;
delete delete_node;
}
}
//环插入
void insert(Node<Type> *node, int index) {
if (head == NULL) {
if (index != 0) {
return;
}
head = node;
head->next = head;
return;
}
if (index == 0) {
node->next = head->next;
head->next = node;
return;
}
Node<Type> *current_node = head->next;
int count = 0;
while (current_node != head && count < index - 1) {
current_node = current_node->next;
count++;
}
if (count == index - 1) {
node->next = current_node->next;
current_node->next = node;
}
if (node == head->next) {
head = node;
}
}
//环输出
void output() {
if (head == NULL) {
return;
}
Node<Type> *current_node = head->next;
Node<Type> *head_node = head->next;
do {
cout << current_node->data << " ";
current_node = current_node->next;
}while (current_node != head_node);
cout << endl;
}
//循环到第m个的人被踢出
void output_josephus(int m) {
if (head == nullptr)
return;
Node<Type> *current_node = head;
head = NULL;
while (current_node->next != current_node) {
for (int i = 1; i < m; ++i) {
current_node = current_node->next;
}
cout << current_node->next->data << " ";
Node<Type> *delete_node = current_node->next;
current_node->next = delete_node->next;
delete delete_node;
}
cout << current_node->data << endl;
delete current_node;
}
};
int main() {
LinkedList<int> linkedlist;
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
Node<int> *node = new Node<int>(i);
linkedlist.insert(node, i - 1);
}
linkedlist.output();
linkedlist.output_josephus(m);
return 0;
}