链表的应用——猴子选大王

问题描述

一群猴子,编号是123……m,这样的一群猴子(m)个按照1-m的顺序围圈坐,从第一只开始数,每数到第n个,该猴子就要离开次圈,这样依次下来至到圈中只剩下最后一只猴子,该猴子则为大王。

程序代码

#include <stdio.h>
#include <stdlib.h>
/*

*csdn学院

*目的:让代码见证成长(作为一个初学的菜鸟,如

*大家有发现错误,欢迎指正!)

*运行软件:CodeBlocks

*作者:小臣小仁

*完成日期:2020年3月15日

*/
struct Monkey
{
    int num;//猴子序号
    struct Monkey *next;//指向下一只猴子
};
int main()
{
    int m,n,i,j,king;
    struct Monkey *head,*p1,*p2;
    printf("输入猴群数量:");
    scanf("%d",&m);
    printf("输入淘汰数:");
    scanf("%d",&n);
    if(n == 1)
    {
        king = m;
    }
    else
    {
        p1 = p2 = (struct Monkey *)malloc(sizeof(struct Monkey));//建立结点
        head = p1;//头结点
        head->num = 1;//第一只猴子
        for(i=1;i<m;i++)//用链表的尾插法
        {
            p1=(struct Monkey *)malloc(sizeof(struct Monkey));//建立新结点
            p1->num=i+1;//记录是第几只猴子
            p2->next = p1;//连接插入的结点
            p2 = p1;//指针始终指向链表尾部的上一个,以等待下一次进行链接
        }
        p2->next = head;//尾指针指向头指针,形成循环单链表

        p1 = head;//将动态指针指向头结点
        for(i=1;i<m;i++)
        {
            for(j=1;j<n-1;j++)
                p1 = p1->next;//经过循环找到第n-1个
            p2 = p1->next;//p2指向最后一个节点
            printf("第%d轮淘汰%d\n",i,p2->num);
            p1->next = p2->next;//将为n的结点摘掉,重新建立链表
            p1 = p2->next;//又指向链表新一轮开始结点
            free(p2);//释放为n的结点
        }
        king = p1->num;
        free(p1);
    }
    printf("猴王是:%d\n",king);
    return 0;
}

运行结果‘

 

### 链表应用编程题目与实训项目示例 #### 示例 1: 倒数第 K 个节点 编写一个函数 `getKthFromEnd`,用于找到单链表中的倒数第 K 个节点。此问题可以通过双指针技术解决,其中一个指针先向前移动 K 步,然后两个指针一起前进直到第一个指针到达末尾[^5]。 ```c struct ListNode* getKthFromEnd(struct ListNode* head, int k){ struct ListNode *slow = head, *fast = head; while (k--){ if (fast) { fast = fast->next; } else { return NULL; } } while (fast){ fast = fast->next; slow = slow->next; } return slow; } ``` --- #### 示例 2: 重排链表 给定一个链表,将其重新排列为如下形式: L0 → Ln → L1 → Ln-1 → L2 → Ln-2 …… 该问题涉及三个主要步骤:查找中间节点、反转后半部分链表以及合并两条链表[^3]。 ```python def reorderList(head): if not head or not head.next: return # Step 1: Find the middle of the list slow, fast = head, head while fast and fast.next: slow = slow.next fast = fast.next.next # Step 2: Reverse the second half prev, curr = None, slow while curr: next_node = curr.next curr.next = prev prev = curr curr = next_node first_half, second_half = head, prev # Step 3: Merge two halves while second_half: temp1, temp2 = first_half.next, second_half.next first_half.next = second_half second_half.next = temp1 first_half = temp1 second_half = temp2 ``` --- #### 示例 3: 图书管理系统中的链表应用 在一个简单的图书管理系统中,可以使用链表来存储书籍信息。每本书可以用一个节点表示,包含书名、作者和其他元数据。通过链表的操作(如插入、删除和遍历),可以实现对书籍的管理[^1]。 ```cpp class BookNode { public: string title; string author; BookNode* next; BookNode(string t, string a): title(t), author(a), next(nullptr) {} }; void addBook(BookNode*& head, string title, string author) { BookNode* newNode = new BookNode(title, author); if (!head) { head = newNode; } else { BookNode* current = head; while (current->next) { current = current->next; } current->next = newNode; } } void displayBooks(const BookNode* head) { const BookNode* current = head; while (current) { cout << "Title: " << current->title << ", Author: " << current->author << endl; current = current->next; } } ``` --- #### 示例 4: C语言基础实训——链表操作 在C语言实训中,学生通常会被要求完成一些基本的链表操作练习,例如创建链表、插入节点、删除节点和遍历链表等。这有助于理解指针的概念及其实际用途[^4]。 ```c #include <stdio.h> #include <stdlib.h> typedef struct Node { int data; struct Node* next; } Node; // 创建新节点 Node* createNode(int value) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = value; newNode->next = NULL; return newNode; } // 插入到链表头部 void insertAtHead(Node** head_ref, int value) { Node* newNode = createNode(value); newNode->next = (*head_ref); (*head_ref) = newNode; } // 打印链表 void printList(Node* node) { while (node != NULL) { printf("%d -> ", node->data); node = node->next; } printf("NULL\n"); } ``` --- #### 示例 5: 动态规划与链表结合 对于某些复杂的算法设计问题,可能需要将动态规划的思想融入链表应用之中。例如,在处理路径优化或者资源分配等问题时,可能会涉及到链表的数据结构配合状态转移方程的设计[^2]。 ```java import java.util.*; public class DPWithLinkedList { public static void main(String[] args) { LinkedList<Integer> dpTable = new LinkedList<>(); // 初始化DP表格 for (int i = 0; i <= n; ++i) { dpTable.add(i == 0 ? 0 : Integer.MAX_VALUE); } // 更新DP值 Iterator<Integer> it = dpTable.iterator(); while(it.hasNext()) { int currentValue = it.next(); // 计算逻辑... } } } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值