| 
 | 
 
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册  
 
x
 
 本帖最后由 UNKNOWN404 于 2024-11-2 15:04 编辑  
 
大家好, 
 
我最近在练习一个算法,通过双向环链表狀问题来找出一个神奇数字,移除全部'X'、只保留'O'。我已经完成了部分代码,但遇到了一些困难,希望得到大家的帮助。 
 
由'O'和'X'组成的字符串,需要通过一个双向链表来模拟这个过程。算法需要从顺时针开始数,遇到第一个'X'时删除它并转换方向,然后重复这个过程。 
 
我已经有了基本的节点定义和链表创建函数,但是不确定如何实现寻找神奇数字的函数。以下是我目前的代码框架: 
 
范例: 
输入:OXOXOXX 
输出:神奇数字为 7 
 
 
- /
 
 - #include <stdio.h>
 
 - #include <stdlib.h>
 
 - #include <string.h> 
 
 - #define MAX_LENGTH 1000
 
  
- /* 定义节点 */
 
 - typedef struct Node {
 
 -     char data;           // 纪录 'O'和'X'
 
 -     struct Node *next;   // 指向下一个节点的指针
 
 -     struct Node *prev;   // 指向前一个节点的指针
 
 - } Node;
 
  
- /* 建立一个新节点的函式 */
 
 - Node *createNode(char data) {
 
 -     // 使用 malloc 分配内存给新节点
 
 -     Node *newNode = (Node*)malloc(sizeof(Node));
 
 -     
 
 -     // 检查内存是否成功分配
 
 -     if (newNode == NULL) {
 
 -         printf("内存分配失败\n");
 
 -         exit(1);  // 如果失败,退出执行 
 
 -     }
 
 -     
 
 -     // 初始化新节点的资料和指针
 
 -     newNode->data = data;
 
 -     newNode->next = NULL;
 
 -     newNode->prev = NULL;
 
 -     
 
 -     return newNode;  // 返回新创建的节点
 
 - }
 
  
- /* 建立双向环状链节串行的函式 */
 
 - Node *createCircularList(char *str) {
 
 -     int i = 0;
 
 -     int len = strlen(str);  // 获取字符串长度
 
 -     if (len == 0) return NULL;  // 如果字符串为空,返回 NULL
 
  
-     Node* head = createNode(str[0]);  // 建立头节点
 
 -     Node* current = head;
 
  
-     // 为字符串中的每个字符创建一个节点并连接
 
 -     for (i = 1; i < len; i++) {
 
 -         Node* newNode = createNode(str[i]);
 
 -         current->next = newNode;
 
 -         newNode->prev = current;
 
 -         current = newNode;
 
 -     }
 
 -     
 
 -     // 将最后一个节点和第一个节点连接,形成双向环状结构
 
 -     current->next = head;
 
 -     head->prev = current;
 
 -     
 
 -     return head;  // 返回头节点
 
 - }
 
  
- /* 计算环状链节串行中节点数量的函式 */
 
 - int countNodes(Node *head) {
 
 -     if (head == NULL) return 0;  // 如果链节串行为空,返回 0
 
  
-     int count = 1;  // 从 1 开始计数(头节点)
 
 -     Node *current = head->next;  // 从第二个节点开始
 
  
-     // 遍历链表直到回到头节点
 
 -     while (current != head) {
 
 -         count++;
 
 -         current = current->next;
 
 -     }
 
  
-     return count;  // 返回节点总数
 
 - }
 
  
- /* 打印双向环状链节串行的函式 */
 
 - void printList(Node* head) {
 
 -     if (head == NULL) {
 
 -         printf("链节串行为空\n");
 
 -         return;
 
 -     }
 
  
-     Node *current = head;
 
 -     do {
 
 -         printf("%c ", current->data);  // 打印当前节点的数据
 
 -         current = current->next;       // 移动到下一个节点
 
 -     } while (current != head);  // 当回到头节点时停止
 
 -     printf("\n");
 
 - }
 
  
- /* 从双向环状链节串行中移除指定节点的函式 */
 
 - Node *removeNode(Node* head, Node* nodeToRemove) {
 
 -     if (head == NULL || nodeToRemove == NULL) {
 
 -         printf("错误:removeNode 函数收到空指针\n");
 
 -         return head;
 
 -     }
 
  
-     // 如果要移除的是头节点
 
 -     if (head == nodeToRemove) {
 
 -         if (head->next == head) {
 
 -             // 如果链节串行中只有一个节点
 
 -             free(head);
 
 -             return NULL;
 
 -         }
 
 -         // 更新头节点
 
 -         Node *newHead = head->next;
 
 -         newHead->prev = head->prev;
 
 -         head->prev->next = newHead;
 
 -         free(head);
 
 -         return newHead;
 
 -     }
 
  
-     // 移除中间的节点
 
 -     nodeToRemove->prev->next = nodeToRemove->next;
 
 -     nodeToRemove->next->prev = nodeToRemove->prev;
 
 -     free(nodeToRemove);
 
  
-     return head;
 
 - }
 
  
 
- /* 释放双向环状链节串行内存的函式 */
 
 - void freeList(Node *head) {
 
 -     if (head == NULL) return;
 
  
-     Node* current = head->next;
 
 -     Node* temp;
 
  
-     // 释放除了头节点外的所有节点
 
 -     while (current != head) {
 
 -         temp = current;
 
 -         current = current->next;
 
 -         free(temp);
 
 -     }
 
  
-     // 释放头节点
 
 -     free(head);
 
 - }
 
  
- /* 修改后的查找神奇数字的函式 */
 
 - int findMagicNumber(Node **head, char *originalStr) {
 
 -     int i = 0;
 
 -     int magicNumber = 1;  // 从 1 开始尝试
 
 -     int isClockwise = 1;  // 1 表示顺时针,0 表示逆时针
 
 -     Node *current = *head;
 
 -     int remainingX = 0;  // 记录剩余的 'X' 数量
 
  
-     // 计算初始 'X' 的数量
 
 -     Node *temp = *head;
 
 -     do {
 
 -         if (temp->data == 'X') remainingX++;
 
 -         temp = temp->next;
 
 -     } while (temp != *head);
 
  
-     // 主循环:持续直到所有 'X' 被移除
 
 -     while (remainingX > 0) {
 
 -         printf("当前链表: ");
 
 -         printList(*head);
 
 -         printf("尝试神奇数字: %d (方向: %s)\n", 
 
 -                magicNumber, 
 
 -                isClockwise ? "顺时针" : "逆时针");
 
  
-         // 移动到第 magicNumber 个节点
 
 -         for (i = 1; i < magicNumber; i++) {
 
 -             if (isClockwise) {
 
 -                 current = current->next;
 
 -             } else {
 
 -                 current = current->prev;
 
 -             }
 
 -         }
 
  
-         // 如果当前节点是 'X',移除它并切换方向
 
 -         if (current->data == 'X') {
 
 -             printf("移除节点: %c\n", current->data);
 
 -             Node *nodeToRemove = current;
 
 -             current = isClockwise ? current->next : current->prev;
 
 -             *head = removeNode(*head, nodeToRemove);
 
 -             remainingX--;
 
  
-             if (*head == NULL) {
 
 -                 printf("错误:链节串行为空\n");
 
 -                 return -1;
 
 -             }
 
  
-             // 切换方向
 
 -             isClockwise = !isClockwise;
 
 -             printf("切换方向为: %s\n", isClockwise ? "顺时针\n" : "逆时针\n");
 
 -         } else {
 
 -             // 如果是 'O',重建链表并重置方向为顺时针
 
 -             printf("遇到 'O',重建链表\n\n");
 
 -             freeList(*head);
 
 -             *head = createCircularList(originalStr);
 
 -             current = *head;
 
 -             isClockwise = 1;  // 重置为顺时针
 
 -             magicNumber++;    // 增加神奇数字
 
 -         }
 
 -     }
 
  
-     return magicNumber;  // 返回找到的神奇数字
 
 - }
 
  
- /* 修改主函数以传递原始字符串 */
 
 - int main() {
 
 -     // 步骤 1: 打开输入文件
 
 -     FILE *file = fopen("input.txt", "r");
 
 -     if (file == NULL) {
 
 -         printf("无法打开 input.txt 文件\n");
 
 -         return 1;
 
 -     }
 
  
-     // 步骤 2: 读取输入字符串
 
 -     char str[MAX_LENGTH];
 
 -     if (fgets(str, MAX_LENGTH, file) == NULL) {
 
 -         printf("无法从 input.txt 读取数据\n");
 
 -         fclose(file);
 
 -         return 1;
 
 -     }
 
 -     fclose(file);
 
  
-     // 步骤 3: 移除字符串末尾的换行符(如果存在)
 
 -     str[strcspn(str, "\n")] = 0;
 
 -     printf("输入: %s\n", str);
 
  
-     // 步骤 4: 创建双向环状链节串行 
 
 -     Node* head = createCircularList(str);
 
 -     if (head == NULL) {
 
 -         printf("创建环状链表失败\n");
 
 -         return 1;
 
 -     }
 
  
-     // 步骤 5: 查找神奇数字,传入原始字符串用于重建
 
 -     int magicNumber = findMagicNumber(&head, str);
 
  
-     // 步骤 6: 输出结果
 
 -     if (magicNumber != -1) {
 
 -         printf("神奇数字为 %d\n", magicNumber);
 
 -     } else {
 
 -         printf("未能找到神奇数字\n");
 
 -     }
 
  
-     // 步骤 7: 释放剩余节点的内存 
 
 -     freeList(head);
 
 -     return 0;
 
 - }
 
 
  复制代码 
你在实现约瑟夫环问题时遇到了一些困难。根据你的描述和代码框架,我注意到了一些需要修正的地方。以下是一些建议和修改: 
1. **字符串读取和处理**: 
   - 你在读取字符串时使用了`char str;`,这应该是一个字符数组而不是单个字符。 
   - 使用`fgets`读取字符串时,确保字符串数组的大小足够大。
 
2. **创建链表**: 
   - 在`createCircularList`函数中,`createNode(str)`应该是`createNode(str[i])`,因为你需要为每个字符创建节点。
 
3. **查找神奇数字的逻辑**: 
   - 在`findMagicNumber`函数中,确保在每次重建链表时正确地重置`current`指针。 
   - 确保在移除节点后,`current`指针指向下一个有效节点。
 
4. **文件读取和字符串处理**: 
   - 确保在读取字符串后移除换行符。 
   - 使用`str[strcspn(str, " 
")] = 0;`来移除换行符。
 
以下是一些修改后的代码片段:
 
希望这些建议和修改能帮助你解决问题!如果有其他问题,欢迎继续提问。
 
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。  
 
 
 |   
 
 
 
 |