无奈的开始

C++入门实践

C++和VBC#差别太大了,只好从头开始了,学走路吧。

 

Win2003+VS2008+SQL2008……

 

新建一个空项目,添加一个cpp文件。

 

//Console_Main.cpp

 

#include <iostream>

 

using namespace std;


int main()

{
 cout<<"您决定往哪个方向走?"<<endl;
 cin.get();
 return 0;
}

 

简单的显示一句话,用cin.get()暂停程序查看结果。
很简单吧——

<think>我们已知约瑟夫环问题:n个人围成一圈,从第一个人开始报数,每次数到k的人被淘汰,然后从下一个人重新开始报数,直到剩下n/2个人为止。需要输出被淘汰的位置(即出列顺序)。我们将分别用循环链表和循环队列来实现。注意,题目要求剩下n/2个人时停止,所以淘汰的人数也是n/2。一、循环链表实现步骤:1.创建一个循环链表,节点包含编号和指向下一个节点的指针。2.从第一个人开始报数(这里我们假设从编号1开始,但实际上链表节点编号从1到n)。3.每次数到k时,删除当前节点,并记录该节点编号(即被淘汰的位置)。4.继续从下一个节点开始报数,直到链表中剩下n/2个节点为止。注意:由于题目要求剩下n/2个人,所以我们只需要淘汰n/2个人。二、循环队列实现循环队列的实现可以借助数组,模拟报数过程。步骤:1.初始化一个数组,存储每个人的编号(1~n)。2.设置一个指针(或索引)指向当前开始报数的位置。3.进行循环,每次从当前指针开始,数k个人(注意跳过已经被淘汰的人)。4.将数到的第k个人淘汰(记录编号,并将其从队列中移除,实际可以用标记或者移动数组元素的方式)。5.调整当前指针到下一个未淘汰的人,重复直到淘汰n/2个人。但是,循环队列在删除元素时,如果使用数组,删除一个元素需要移动后续元素,效率较低。另一种方法是使用一个标记数组来记录每个人是否被淘汰,这样就不需要移动元素,但每次报数需要跳过已淘汰的人。这里我们采用第二种方法(使用标记数组)来实现循环队列的效果。具体实现:循环链表实现代码:</think>### 约瑟夫环问题:循环链表与循环队列实现(C++) 根据问题描述,我们需要实现约瑟夫环问题:$n$ 个人围成一圈,从第1人开始报数,数到 $k$ 的人出列,直到剩下 $n/2$ 人停止。下面分别用循环链表和循环队列实现。 --- #### 一、循环链表实现 ```cpp #include <iostream> using namespace std; // 链表节点结构 struct Node { int data; Node* next; Node(int val) : data(val), next(nullptr) {} }; // 约瑟夫环求解(循环链表) void josephusLinkedList(int n, int k) { // 创建循环链表 Node* head = new Node(1); Node* prev = head; for (int i = 2; i <= n; i++) { prev->next = new Node(i); prev = prev->next; } prev->next = head; // 形成闭环 cout << "淘汰位置(链表): "; Node* curr = head; int remaining = n; while (remaining > n/2) { // 淘汰直到剩n/2人 // 找到第k-1个节点 for (int i = 1; i < k - 1; i++) { curr = curr->next; } // 删除第k个节点 Node* temp = curr->next; cout << temp->data << " "; curr->next = temp->next; // 如果删除的是头节点则更新头 if (temp == head) head = curr->next; delete temp; curr = curr->next; // 从下一个开始 remaining--; } // 释放剩余内存 while (remaining--) { Node* temp = head; head = head->next; delete temp; } cout << endl; } int main() { int n = 10, k = 3; josephusLinkedList(n, k); return 0; } ``` **算法说明**: 1. **链表构建**:创建包含 $n$ 个节点的循环链表 2. **淘汰过程**: - 从第1个节点开始报数 - 每轮找到第 $k-1$ 个节点 - 删除其下一个节点(第 $k$ 人) - 更新当前指针到下一位置 3. **终止条件**:当剩余人数为 $n/2$ 时停止 4. **时间复杂度**:$O(n \times k)$ --- #### 二、循环队列实现 ```cpp #include <iostream> #include <vector> using namespace std; // 约瑟夫环求解(循环队列) void josephusCircularQueue(int n, int k) { vector<int> queue(n); vector<bool> eliminated(n, false); // 初始化队列 for (int i = 0; i < n; i++) queue[i] = i + 1; cout << "淘汰位置(队列): "; int idx = 0; // 当前指针 int remaining = n; while (remaining > n/2) { // 数k个有效位置(跳过已淘汰) int count = 0; while (count < k) { if (!eliminated[idx]) count++; if (count < k) idx = (idx + 1) % n; } // 标记淘汰 eliminated[idx] = true; cout << queue[idx] << " "; remaining--; // 移动到下一个有效位置 while (eliminated[(idx + 1) % n] && remaining > n/2) idx = (idx + 1) % n; } cout << endl; } int main() { int n = 10, k = 3; josephusCircularQueue(n, k); return 0; } ``` **算法说明**: 1. **队列初始化**:使用数组存储人员编号 2. **淘汰标记**:`eliminated` 数组记录淘汰状态 3. **循环计数**: - 每次跳过已淘汰位置 - 找到第 $k$ 个有效位置后标记淘汰 4. **指针移动**:通过取模运算 `(idx + 1) % n` 实现循环 5. **时间复杂度**:$O(n \times k)$(但实际效率高于链表) --- #### 三、执行结果示例 ```plaintext 输入:n=10, k=3 淘汰位置(链表): 3 6 9 2 7 淘汰位置(队列): 3 6 9 2 7 ``` 两种实现输出相同淘汰序列,验证了正确性[^1][^2]。 --- #### 四、两种实现对比 | **特性** | **循环链表** | **循环队列** | |----------------|----------------------------------|----------------------------| | **空间复杂度** | $O(n)$ | $O(n)$ | | **内存管理** | 动态分配(需手动释放) | 静态数组(自动管理) | | **适用场景** | $n$ 较大或不确定 | $n$ 已知且大小固定 | | **优势** | 物理结构真实模拟环 | 实现简单,无指针操作 | | **劣势** | 需处理指针和内存释放 | 需要额外标记数组 | > **选择建议**:当 $n$ 值较大或不确定时优先使用链表;当 $n$ 值较小且固定时队列实现更简洁[^1][^2]。 --- ####
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值