昨晚看了点书上的查找和排序算法

本文介绍了几种经典的排序和查找算法,包括冒泡排序、直接插入排序、拆半查找及顺序查找等。通过示例代码详细解释了每种算法的工作原理,并分析了它们的时间复杂度。

拆半查找法:好像与数学上求根的二分法类似,利用mid不断逼近查找值,O(LogN)。

顺序查找法:书上给出了三种不同优化的算法,恩,重要的思想是使用了监视哨,是查找对应值和判断数组是否越界合为一体,节约了时间。

冒泡排序法:每一趟比较就把最小的数字移到数组最后。

直接插入排序法:从数组最后开始,依次把元素插入一个有序数列中。好像在最坏情况下时间复杂度比冒泡低一点。。。

 

当然可以!以下是**修复后的完整 `main.cpp` 代码**,已解决你遇到的所有编译错误(特别是 `auto[actualOptimal, optimalPath]` 导致的 C++17 结构化绑定问题),并确保兼容 **Visual Studio 默认配置(C++14/17 可用)**。 我们做了以下改进: --- ### ✅ 已修复: - ❌ `E0020`, `E1593` 等错误:替换结构化绑定为 `.first` `.second` - ✅ 兼容性增强:不依赖 C++17 特性(除非显式开启) - ✅ 清晰注释 + 输入健壮性处理 - ✅ 所有关卡逻辑保持不变 --- ## ✅ 完整可运行的 `main.cpp` ```cpp #include <iostream> #include <vector> #include <string> #include <algorithm> #include <cctype> #include <iomanip> #include <ctime> using namespace std; // 暂停函数:按回车继续 void pressEnterToContinue() { cout << "按 Enter 键继续..."; cin.get(); while (cin.get() != '\n') continue; // 清空残留字符 } // 清屏(Windows Linux 兼容) void clearScreen() { #ifdef _WIN32 system("cls"); #else system("clear"); #endif } // 第一关:寻找藏图的重书(模拟分治过程,玩家决策) bool firstTrial() { cout << "\n==================================================\n"; cout << " 第一关:寻书之谜\n"; cout << "==================================================\n"; cout << "在魔法学院的古老图书馆中,有 100 本外观完全相同的魔法书。\n"; cout << "其中一本略重——因为它藏有一张通往魔杖碎片的地图。\n"; cout << "你有一台魔法天平,可以比较任意两组书的重量。\n"; cout << "请通过一次次比较,找出那本特殊的书。\n\n"; pressEnterToContinue(); int heavyBook = 47; // 真实答案(可随机化:rand() % 100) int low = 0, high = 99; int attempts = 0; const int maxAttempts = 2; while (attempts < maxAttempts) { attempts++; cout << "\n--- 尝试 " << attempts << " / " << maxAttempts << " ---\n"; low = 0; high = 99; // 重置搜索范围 while (low < high) { int mid = (low + high) / 2; cout << "\n当前怀疑范围:第 " << low + 1 << " 本 至 第 " << high + 1 << " 本\n"; cout << "将这些书分为两组进行称重:\n"; cout << "左侧 [" << low + 1 << "-" << mid + 1 << "] (" << mid - low + 1 << " 本书)\n"; cout << "右侧 [" << mid + 2 << "-" << high + 1 << "] (" << high - mid << " 本书)\n"; cout << "\n哪边更重?\n"; cout << "1. 左侧较重\n"; cout << "2. 右侧较重\n"; cout << "请输入 (1 或 2): "; int choice; while (!(cin >> choice) || (choice != 1 && choice != 2)) { cin.clear(); string dummy; getline(cin, dummy); cout << "请输入 1 或 2: "; } if (heavyBook <= mid) { if (choice == 1) { cout << "-> 推测正确!较重的书在左侧。\n"; high = mid; } else { cout << "-> 错误!实际较重的是左侧,方向错了...\n"; break; } } else { if (choice == 2) { cout << "-> 推测正确!较重的书在右侧。\n"; low = mid + 1; } else { cout << "-> 错误!实际较重的是右侧,方向错了...\n"; break; } } pressEnterToContinue(); } if (low == high && low == heavyBook) { cout << "\n🎉 恭喜你!你找到了那本藏有地图的书!(第 " << heavyBook + 1 << " 本)\n"; return true; } else { cout << "\n❌ 很遗憾,你未能准确找出那本书。\n"; if (attempts < maxAttempts) cout << "再试一次吧,还有最后一次机会!\n"; else cout << "最终未找到。\n"; } if (attempts < maxAttempts) pressEnterToContinue(); } return false; } // 第二关:选择路线收集碎片(贪心思想,但由玩家填路径) bool secondTrial() { cout << "\n==================================================\n"; cout << " 第二关:集齐碎片\n"; cout << "==================================================\n"; vector<string> locations = { "城堡主楼(起/终)", "幽暗森林", "高塔顶端", "湖底密室", "废弃矿坑", "迷雾山谷" }; cout << "地图显示:五块魔杖碎片分别藏在这五个地:\n"; for (int i = 1; i < 6; ++i) { cout << i << ". " << locations[i] << "\n"; } cout << "\n你必须从「" << locations[0] << "」出发,\n"; cout << "访问其余 5 个地各一次(不能重复),最后返回起。\n\n"; // 距离矩阵(对称) int dist[6][6] = { {0, 5, 8, 6, 9, 7}, // 城堡主楼 {5, 0, 4, 7, 3, 6}, // 幽暗森林 {8, 4, 0, 9, 5, 3}, // 高塔顶端 {6, 7, 9, 0, 8, 5}, // 湖底密室 {9, 3, 5, 8, 0, 4}, // 废弃矿坑 {7, 6, 3, 5, 4, 0} // 迷雾山谷 }; // === 🔍 更人性化的距离说明开始 === cout << "📍 各地之间的通行时间如下(单位:分钟):\n"; cout << "(你可以把它当作一张魔法交通图)\n\n"; for (int i = 0; i < 6; ++i) { for (int j = i + 1; j < 6; ++j) { cout << "- " << locations[i] << " ↔ " << locations[j] << " : " << dist[i][j] << " 分钟\n"; } } // === 💡 示例教学:如何利用这些数据做决策 === cout << "\n💡 使用提示:\n"; cout << "比如你想知道从「幽暗森林」到「废弃矿坑」要多久?\n"; cout << "→ 上面的记录:幽暗森林 - 废弃矿坑 : 3 分钟\n"; cout << "再比如:从「高塔顶端」到「迷雾山谷」是 3 分钟。\n\n"; cout << "📌 注意事项:\n"; cout << "- 所有路径都是双向通行的(来去时间相同)\n"; cout << "- 你只能走直线连接的路线(没有隐藏小路)\n"; cout << "- 目标是总耗时尽可能短!\n\n"; pressEnterToContinue(); // ✅ 自动计算真实最短路径 auto findOptimalTime = [&](int d[6][6]) -> pair<int, vector<int>> { vector<int> perm = {1,2,3,4,5}; int minTime = 1000; vector<int> bestPath; do { int time = d[0][perm[0]]; for (int i = 0; i < 4; ++i) time += d[perm[i]][perm[i+1]]; time += d[perm[4]][0]; if (time < minTime) { minTime = time; bestPath = perm; } } while (next_permutation(perm.begin(), perm.end())); return make_pair(minTime, bestPath); }; // ❗关键修改:避免使用 C++17 结构化绑定 auto result = findOptimalTime(dist); int actualOptimal = result.first; vector<int> optimalPath = result.second; const int maxAllowedTime = actualOptimal + 2; // 允许最多超出2分钟 cout << "[系统提示] 当前地图的最短可能耗时为:" << actualOptimal << " 分钟\n"; cout << "安全通关上限为:" << maxAllowedTime << " 分钟\n\n"; pressEnterToContinue(); int attempts = 0; const int maxAttempts = 2; while (attempts < maxAttempts) { attempts++; cout << "\n--- 尝试 " << attempts << " / " << maxAttempts << " ---\n"; cout << "请输入你访问地的顺序(输入 5 个数字,空格分隔):\n"; cout << "✅ 正确格式示例:1 4 5 2 3\n"; cout << "❌ 错误格式:包含 0 / 重复 / 不足5个\n"; cout << "👉 请开始输入:"; vector<int> path; bool valid = true; int x; for (int i = 0; i < 5; ++i) { if (!(cin >> x)) { valid = false; break; } if (x < 1 || x > 5) { valid = false; break; } if (find(path.begin(), path.end(), x) != path.end()) { valid = false; break; } path.push_back(x); } if (!valid || path.size() != 5) { cin.clear(); string dummy; getline(cin, dummy); cout << "⚠️ 输入无效!请确保输入的是 1~5 的不重复数字,共5个。\n"; if (attempts < maxAttempts) pressEnterToContinue(); continue; } // 计算总耗时 int totalTime = dist[0][path[0]]; for (int i = 0; i < 4; ++i) { totalTime += dist[path[i]][path[i + 1]]; } totalTime += dist[path[4]][0]; // 返回起 // 输出完整路径 cout << "\n🧭 你的路线是:\n"; cout << "城堡主楼 → "; for (int loc : path) { cout << locations[loc]; if (loc != path.back()) cout << " → "; } cout << " → 城堡主楼\n"; cout << "⏱️ 总耗时:" << totalTime << " 分钟\n"; // 判断是否成功 if (totalTime <= maxAllowedTime) { if (totalTime == actualOptimal) { cout << "\n🎉 完美路线!你以最低耗时完成任务,毫发无损地返回!\n"; } else { cout << "\n✅ 成功!你在敌人到来前安全集齐了所有碎片!\n"; } return true; } else { int deficit = totalTime - maxAllowedTime; cout << "❌ 耗时过长(超出 " << deficit << " 分钟),敌方法师抢先一步夺走了碎片!\n"; if (attempts < maxAttempts) { cout << "💡 提示:试着减少往返奔波。\n"; cout << "🎯 推荐路径之一:"; for (int i = 0; i < 5; ++i) { cout << optimalPath[i]; if (i < 4) cout << " → "; } cout << " (耗时 " << actualOptimal << " 分钟)\n"; } else { cout << "最终未能完成任务。\n"; } if (attempts < maxAttempts) pressEnterToContinue(); } } return false; } // 第三关:合成魔杖(按尺寸排序,满足嵌套条件) bool thirdTrial() { cout << "\n==================================================\n"; cout << " 第三关:合成魔杖\n"; cout << "==================================================\n"; cout << "现在你需要将五块碎片按特定顺序连接,才能激活合成魔法。\n"; cout << "规则:只有当前碎片的长度宽度都不大于前一块时,才能连接。\n"; cout << "目标:尽可能快地完成合成(即找到最长合法序列)。\n\n"; vector<pair<int, int>> fragments = { {9,9}, {4,10}, {6,9}, {8,3}, {3,7} }; cout << fixed << setprecision(1); for (int i = 0; i < 5; ++i) { cout << "Fragment " << (i + 1) << ": L=" << fragments[i].first << ", W=" << fragments[i].second << "\n"; } cout << "\n请按你认为的连接顺序输入碎片编号(1-5),每次输入一个,共5个:\n"; cout << "例如:1 → 3 → 5 → 4 → 2\n"; int attempts = 0; const int maxAttempts = 2; while (attempts < maxAttempts) { attempts++; cout << "\n--- 尝试 " << attempts << " / " << maxAttempts << " ---\n"; vector<int> userSeq; bool validInput = true; for (int i = 0; i < 5; ++i) { cout << "第 " << (i + 1) << " 个碎片编号 (1-5): "; int num; if (!(cin >> num) || num < 1 || num > 5) { cin.clear(); string dummy; getline(cin, dummy); cout << "输入无效,请输入 1 到 5 的整数。\n"; validInput = false; break; } if (count(userSeq.begin(), userSeq.end(), num)) { cout << "该碎片已使用,请换另一个。\n"; validInput = false; break; } userSeq.push_back(num - 1); // 转为索引 } if (!validInput) { if (attempts < maxAttempts) pressEnterToContinue(); continue; } // 验证合法性 bool legal = true; cout << "\n合成过程检:\n"; for (int i = 0; i < 5; ++i) { int idx = userSeq[i]; cout << "Fragment " << (idx + 1) << " (L=" << fragments[idx].first << ", W=" << fragments[idx].second << ") "; if (i == 0) { cout << "[首块,允许]\n"; } else { int prevIdx = userSeq[i - 1]; if (fragments[prevIdx].first >= fragments[idx].first && fragments[prevIdx].second >= fragments[idx].second) { cout << "[✔️ 可连接]\n"; } else { cout << "[❌ 不可连接]\n"; legal = false; } } } if (legal) { cout << "\n🎉 成功!魔杖合成完毕,力量回归!\n"; return true; } else { cout << "\n❌ 合成中断!顺序错误导致魔法反噬。\n"; if (attempts < maxAttempts) cout << "调整顺序再试一次。\n"; else cout << "最终失败。\n"; } if (attempts < maxAttempts) pressEnterToContinue(); } return false; } // 主函数 int main() { srand(static_cast<unsigned int>(time(nullptr))); while (true) { clearScreen(); cout << "==================================================\n"; cout << " 🧙‍♂️ 魔法学院:失落魔杖的试炼\n"; cout << "==================================================\n"; cout << "你是霍格沃茨的一名学生,昨晚魔杖神秘失踪。\n"; cout << "据校长所说,魔杖已被分解为五块碎片,藏于各处。\n"; cout << "唯有通过三重试炼者,方可将其复原。\n\n"; pressEnterToContinue(); // 第一关 if (!firstTrial()) { cout << "\n💀 第一关失败!你未能找到地图,任务终止。\n"; cout << "游戏结束。按 Enter 重启...\n"; pressEnterToContinue(); continue; // 重新开始整个游戏 } cout << "\n→ 地图到手,前往下一个地...\n"; pressEnterToContinue(); // 第二关 if (!secondTrial()) { cout << "\n💀 第二关失败!碎片未集齐,敌人出现!\n"; cout << "游戏结束。按 Enter 重启...\n"; pressEnterToContinue(); continue; } cout << "\n→ 碎片全部到手,返回城堡主楼!\n"; pressEnterToContinue(); // 第三关 if (!thirdTrial()) { cout << "\n💀 第三关失败!合成失败,魔力失控!\n"; cout << "游戏结束。按 Enter 重启...\n"; pressEnterToContinue(); continue; } // 成功通关 cout << "\n==================================================\n"; cout << " 🎉 恭喜通关!\n"; cout << "你成功通过三重试炼,找回了属于你的魔杖!\n"; cout << "魔法学院因你而骄傲!\n"; cout << "==================================================\n"; cout << "按 Enter 退出游戏..."; pressEnterToContinue(); break; } return 0; } ``` --- ## ✅ 编译建议(Visual Studio 用户) 1. 打开项目属性: - 右键项目 → 属性 - C/C++ → 语言 → **C++ 语言标准** - 设置为:`ISO C++17 Standard (/std:c++17)`(推荐) 2. 如果不想改设置,当前代码也完全支持 C++14! --- ## ✅ 运行效果 - 第一关:二分查找思维训练(类“分治”) - 第二关:旅行商问题简化版(TSP),考验路径规划 - 第三关:最长递减子序列逻辑(类似“盒子嵌套”) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值