Zhong__Python迭代器/生成器

时间:2020.12.11

环境:Python3

目的:迭代器/生成器学习

说明:

作者:Zhong QQ交流群:121160124 欢迎加入!

 

迭代器

迭代是Python最强大的功能之一,是访问集合元素的一种方式。

迭代器是一个可以记住遍历的位置的对象。

迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。

迭代器有两个基本的方法:iter()next()

字符串,列表或元组对象都可用于创建迭代器

import sys

# 定义一个列表
ls = ["a","b"]

# 创建迭代器对象
iter_obj = iter(ls)

# 查看类型
print(type(iter_obj))  # <class 'list_iterator'>

# # 输出迭代器的下一个元素
# print(next(iter_obj))  # a
#
# # 输出迭代器的下一个元素
# print(next(iter_obj))  # b
#
# # 输出迭代器的下一个元素
# print(next(iter_obj))  # StopIteration

while True:
    try:
        print(next(iter_obj))
    except StopIteration:
        sys.exit()

 

把一个类作为一个迭代器使用需要在类中实现两个方法 __iter__() 与 __next__() 。

如果你已经了解的面向对象编程,就知道类都有一个构造函数,Python 的构造函数为 __init__(), 它会在对象初始化的时候执行。

__iter__() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 __next__() 方法并通过 StopIteration 异常标识迭代的完成。

__next__() 方法(Python 2 里是 next())会返回下一个迭代器对象。

创建一个返回数字的迭代器,初始值为 1,逐步递增 1:

class MyNumbers:
    def __iter__(self):
        self.a = 1
        return self
    def __next__(self):

        x = self.a
        self.a += 1
        return x

myclass = MyNumbers()
myiter = iter(myclass)

print(next(myiter))  # 1
print(next(myiter))  # 2
print(next(myiter))  # 3  
print(next(myiter))  # 4
print(next(myiter))  # 5

StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况,在 __next__() 方法中我们可以设置在完成指定循环次数后触发 StopIteration 异常来结束迭代。

 

生成器

在 Python 中,使用了 yield 的函数被称为生成器(generator)。

跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。

在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。

调用一个生成器函数,返回的是一个迭代器对象。

以下实例使用 yield 实现斐波那契数列:

import sys

def fibonacci(n):  # 生成器函数 - 斐波那契
    a, b, counter = 0, 1, 0
    while True:
        if (counter > n):
            return
        yield a
        a, b = b, a + b
        counter += 1

f = fibonacci(10)  # f 是一个迭代器,由生成器返回生成

while True:
    try:
        print(next(f), end=" ")  # 0 1 1 2 3 5 8 13 21 34 55 
    except StopIteration:
        sys.exit()

 

关注微信公众号

 

 

 

 

#include <Windows.h> #include <string> #include <vector> #include <unordered_map> #include <queue> #include <climits> #include <sstream> #include "Resource.h" // 登录对话框的消息处理函数 INT_PTR CALLBACK LoginDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_COMMAND: if (wp == IDOK || wp == IDCANCEL) { EndDialog(hDlg, wp); return TRUE; } break; case WM_CLOSE: EndDialog(hDlg, IDCANCEL); return TRUE; } return FALSE; } // 主界面对话框的消息处理函数(修改) INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_COMMAND: if (wp == IDOK || wp == IDCANCEL) { EndDialog(hDlg, wp); return TRUE; } break; case WM_CLOSE: EndDialog(hDlg, IDCANCEL); return TRUE; } return FALSE; } // 定义校园地点(顶点) enum CampusPlace { PLACE_BEI_DAMEN, // 北大门 PLACE_XI_DAMEN, // 西大门 PLACE_NAN_DAMEN, // 南大门 PLACE_SONGSHAN_HU, // 松山湖 PLACE_XIN_TIYU_CHANG, // 新体育场 PLACE_OLD_TIYU_CHANG, // 老体育场 PLACE_LEQUN_LOU, // 乐群楼 PLACE_QIUZHEN_LOU, // 求真楼 PLACE_JINGYE_LOU, // 敬业楼 PLACE_HOU_CUN_G1, // 乐业楼 PLACE_HAI_TANG_YUAN, // 海棠苑 PLACE_WU_TONG_YUAN, // 梧桐苑 PLACE_XUE_SHU_JIAO_LIU_ZHONG_XIN ,// 学术交流中心 PLACE_SHUANG_CHUANG_LOU, //双创大楼 PLACE_GONG_YE_ZHONG_XIN, //工业中心 PLACE_XING_ZHEN_LOU, //行政楼 PLACE_JUN_ZHU_YUAN, //筠竹苑 PLACE_XIANG_ZHANG_YUN, //香樟苑 PLACE_SAN_SI_SHI_TANG, //第二食堂 PLACE_YI_ER_SHI_TANG, //第一食堂 }; // 地点名称映射 const std::unordered_map<CampusPlace, std::wstring> PlaceNames = { {PLACE_BEI_DAMEN, L"北大门"}, {PLACE_XI_DAMEN, L"西大门"}, {PLACE_NAN_DAMEN, L"南大门"}, {PLACE_SONGSHAN_HU, L"松山湖"}, {PLACE_XIN_TIYU_CHANG, L"新体育场"}, {PLACE_OLD_TIYU_CHANG, L"老体育场"}, {PLACE_LEQUN_LOU, L"乐群楼"}, {PLACE_QIUZHEN_LOU, L"求真楼"}, {PLACE_JINGYE_LOU, L"敬业楼"}, {PLACE_HOU_CUN_G1, L"乐业楼"}, {PLACE_HAI_TANG_YUAN, L"海棠苑"}, {PLACE_WU_TONG_YUAN, L"梧桐苑"}, {PLACE_XUE_SHU_JIAO_LIU_ZHONG_XIN, L"学术交流中心"}, {PLACE_SHUANG_CHUANG_LOU, L"双创大楼"}, {PLACE_GONG_YE_ZHONG_XIN,L"工业中心"}, {PLACE_XING_ZHEN_LOU,L"行政楼"}, {PLACE_JUN_ZHU_YUAN,L"筠竹苑"}, {PLACE_XIANG_ZHANG_YUN,L"香樟苑"}, {PLACE_SAN_SI_SHI_TANG,L"第二食堂"}, {PLACE_YI_ER_SHI_TANG,L"第一食堂"} }; // 优化后的校园地图邻接表 std::unordered_map<CampusPlace, std::vector<std::pair<CampusPlace, int>>> CampusGraph = { // 北大门 {PLACE_BEI_DAMEN, { {PLACE_HOU_CUN_G1, 8}, // 北大门 → 乐业楼 (8分钟) {PLACE_XIN_TIYU_CHANG, 8}, // 北大门 → 新体育场 (8分钟) {PLACE_QIUZHEN_LOU, 15}, // 北大门 → 求真楼 (15分钟,直达) { PLACE_SHUANG_CHUANG_LOU, 3}, {PLACE_GONG_YE_ZHONG_XIN,2}, {PLACE_SAN_SI_SHI_TANG,10}, }}, // 西大门 {PLACE_XI_DAMEN, { {PLACE_WU_TONG_YUAN, 3}, // 西大门 → 梧桐苑 (3分钟) {PLACE_HAI_TANG_YUAN, 5}, // 西大门 → 海棠苑 (5分钟) {PLACE_LEQUN_LOU, 10} // 西大门 → 乐群楼 (10分钟) }}, // 南大门 {PLACE_NAN_DAMEN, { {PLACE_XUE_SHU_JIAO_LIU_ZHONG_XIN, 3}, // 南大门 → 学术交流中心 (3分钟) {PLACE_JINGYE_LOU, 12}, // 南大门 → 敬业楼 (12分钟) {PLACE_SONGSHAN_HU, 15} // 南大门 → 松山湖 (15分钟) }}, // 松山湖 {PLACE_SONGSHAN_HU, { {PLACE_XIN_TIYU_CHANG, 3}, // 松山湖 → 新体育场 (3分钟) {PLACE_OLD_TIYU_CHANG, 4}, // 松山湖 → 老体育场 (4分钟) {PLACE_HAI_TANG_YUAN, 6}, // 松山湖 → 海棠苑 (6分钟) {PLACE_NAN_DAMEN, 15} // 松山湖 → 南大门 (15分钟) }}, // 新体育场 {PLACE_XIN_TIYU_CHANG, { {PLACE_BEI_DAMEN, 8}, // 新体育场 → 北大门 (8分钟) {PLACE_SONGSHAN_HU, 3}, // 新体育场 → 松山湖 (3分钟) {PLACE_OLD_TIYU_CHANG, 5} // 新体育场 → 老体育场 (5分钟) }}, // 老体育场 {PLACE_OLD_TIYU_CHANG, { {PLACE_SONGSHAN_HU, 4}, // 老体育场 → 松山湖 (4分钟) {PLACE_XIN_TIYU_CHANG, 5}, // 老体育场 → 新体育场 (5分钟) {PLACE_LEQUN_LOU, 2} // 老体育场 → 乐群楼 (2分钟) }}, // 乐群楼 {PLACE_LEQUN_LOU, { {PLACE_OLD_TIYU_CHANG, 2}, // 乐群楼 → 老体育场 (2分钟) {PLACE_QIUZHEN_LOU, 3}, // 乐群楼 → 求真楼 (3分钟) {PLACE_JINGYE_LOU, 4}, // 乐群楼 → 敬业楼 (4分钟) {PLACE_XI_DAMEN, 10} // 乐群楼 → 西大门 (10分钟) }}, // 求真楼 {PLACE_QIUZHEN_LOU, { {PLACE_LEQUN_LOU, 3}, // 求真楼 → 乐群楼 (3分钟) {PLACE_BEI_DAMEN, 15}, // 求真楼 → 北大门 (15分钟) {PLACE_JINGYE_LOU, 2} // 求真楼 → 敬业楼 (2分钟) }}, // 敬业楼 {PLACE_JINGYE_LOU, { {PLACE_LEQUN_LOU, 4}, // 敬业楼 → 乐群楼 (4分钟) {PLACE_QIUZHEN_LOU, 2}, // 敬业楼 → 求真楼 (2分钟) {PLACE_NAN_DAMEN, 12} // 敬业楼 → 南大门 (12分钟) }}, // 乐业楼 {PLACE_HOU_CUN_G1, { {PLACE_BEI_DAMEN, 5}, // 航训楼G1 → 北大门 (5分钟) {PLACE_XIN_TIYU_CHANG, 10}, // 航训楼G1 → 新体育场 (10分钟) {PLACE_LEQUN_LOU, 4} }}, // 海棠苑 {PLACE_HAI_TANG_YUAN, { {PLACE_SONGSHAN_HU, 6}, // 海棠苑 → 松山湖 (6分钟) {PLACE_WU_TONG_YUAN, 2}, // 海棠苑 → 梧桐苑 (2分钟) {PLACE_XI_DAMEN, 5} // 海棠苑 → 西大门 (5分钟) }}, // 梧桐苑 {PLACE_WU_TONG_YUAN, { {PLACE_HAI_TANG_YUAN, 2}, // 梧桐苑 → 海棠苑 (2分钟) {PLACE_XI_DAMEN, 3} // 梧桐苑 → 西大门 (3分钟) }}, // 学术交流中心 {PLACE_XUE_SHU_JIAO_LIU_ZHONG_XIN, { {PLACE_NAN_DAMEN, 3}, // 学术交流中心 → 南大门 (3分钟) {PLACE_JINGYE_LOU, 10} // 学术交流中心 → 敬业楼 (10分钟) }} }; // Dijkstra算法:计算起点到终点的最短路径 std::pair<std::vector<CampusPlace>, int> DijkstraShortestPath(CampusPlace start, CampusPlace end) { // 距离数组:记录每个地点的最短距离 std::unordered_map<CampusPlace, int> dist; // 前驱节点数组:记录路径 std::unordered_map<CampusPlace, CampusPlace> prev; // 优先队列(小顶堆):存储 (当前距离, 地点) std::priority_queue<std::pair<int, CampusPlace>, std::vector<std::pair<int, CampusPlace>>, std::greater<std::pair<int, CampusPlace>>> pq; // 1. 初始化所有距离为无穷大 for (const auto& entry : CampusGraph) { dist[entry.first] = INT_MAX; prev[entry.first] = (CampusPlace)-1; } // 起点到自身的距离为0 dist[start] = 0; pq.push({0, start}); while (!pq.empty()) { // 2. 取出当前距离最小的节点 auto current = pq.top().second; pq.pop(); // 如果已经到达终点,可以提前退出以提高效率 if (current == end) { break; } // 3. 遍历当前节点的所有邻居 for (const auto& neighbor_pair : CampusGraph[current]) { CampusPlace next_place = neighbor_pair.first; int weight = neighbor_pair.second; // 4. 松弛操作:更新距离 if (dist[current] != INT_MAX && dist[next_place] > dist[current] + weight) { dist[next_place] = dist[current] + weight; prev[next_place] = current; // 更新前驱节点 pq.push({dist[next_place], next_place}); } } } // 5. 从终点回溯到起点,重建路径 std::vector<CampusPlace> path; if (dist[end] != INT_MAX) { // 只有当终点可达时才重建路径 for (CampusPlace p = end; p != (CampusPlace)-1; p = prev[p]) { path.push_back(p); } std::reverse(path.begin(), path.end()); // 反转路径,使其从起点到终点 } // 返回路径和总距离,如果不可达,总距离为-1 return {path, dist[end] == INT_MAX ? -1 : dist[end]}; } // 导航对话框的消息处理函数 INT_PTR CALLBACK NaviDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_INITDIALOG: { // 初始化起点/终点下拉框 HWND hComboStart = GetDlgItem(hDlg, IDC_COMBO_START); HWND hComboEnd = GetDlgItem(hDlg, IDC_COMBO_END); // 向下拉框添加地点选项 for (const auto& entry : PlaceNames) { SendMessage(hComboStart, CB_ADDSTRING, 0, (LPARAM)entry.second.c_str()); SendMessage(hComboEnd, CB_ADDSTRING, 0, (LPARAM)entry.second.c_str()); } // 默认选择第一个选项 SendMessage(hComboStart, CB_SETCURSEL, 0, 0); SendMessage(hComboEnd, CB_SETCURSEL, 1, 0); return TRUE; } case WM_COMMAND: { if (LOWORD(wp) == IDC_BTN_QUERY) { // 点击“查询路径”按钮 HWND hComboStart = GetDlgItem(hDlg, IDC_COMBO_START); HWND hComboEnd = GetDlgItem(hDlg, IDC_COMBO_END); HWND hEditPath = GetDlgItem(hDlg, IDC_EDIT_PATH); // 获取选择的起点/终点索引 int startIdx = SendMessage(hComboStart, CB_GETCURSEL, 0, 0); int endIdx = SendMessage(hComboEnd, CB_GETCURSEL, 0, 0); if (startIdx == CB_ERR || endIdx == CB_ERR) { MessageBox(hDlg, L"请选择起点和终点!", L"提示", MB_ICONINFORMATION); return TRUE; } // 转换为CampusPlace枚举 CampusPlace start = (CampusPlace)startIdx; CampusPlace end = (CampusPlace)endIdx; // 计算最短路径 auto [path, totalTime] = DijkstraShortestPath(start, end); if (path.empty() || totalTime == INT_MAX) { SetWindowText(hEditPath, L"无法到达该地点!"); return TRUE; } // 格式化路径文本 std::wstringstream ss; ss << L"最短路径(步行约" << totalTime << L"分钟):\n"; for (size_t i = 0; i < path.size(); ++i) { ss << PlaceNames.at(path[i]); if (i != path.size() - 1) ss << L" → "; } SetWindowText(hEditPath, ss.str().c_str()); return TRUE; } // 处理关闭/取消按钮 else if (LOWORD(wp) == IDOK || LOWORD(wp) == IDCANCEL) { EndDialog(hDlg, LOWORD(wp)); return TRUE; } break; } case WM_CLOSE: { EndDialog(hDlg, IDCANCEL); return TRUE; } } return FALSE; } int APIENTRY wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int) { // 1. 显示登录对话框 INT_PTR nLoginResult = DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG1), nullptr, LoginDlgProc); // 2. 如果登录成功(点击“确定”),显示主界面 if (nLoginResult == IDOK) { INT_PTR nMainResult = DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG2), nullptr, MainDlgProc); // 3. 如果主界面点击“确定”,显示导航界面 if (nMainResult == IDOK) { DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG3), nullptr, NaviDlgProc); } } // 所有界面关闭后,程序退出 return 0; }在这段程序上添加哈夫曼编码和解码 和走迷宫(图的遍历算法)
最新发布
11-28
你当前的程序是一个基于 Windows API 的校园导航系统,使用了 **Dijkstra 算法**实现最短路径查询。现在你想在此基础上添加两个新功能: 1. **哈夫曼编码与解码(Huffman Coding)** 2. **走迷宫(图的遍历算法,如 DFS/BFS)** 我们将逐步在现有项目中集成这两个模块,并给出完整代码和解释。 --- ## ✅ 一、添加:哈夫曼编码与解码 ### 功能说明 - 哈夫曼编码用于数据压缩。 - 给定一段文本,统计字符频率,构建哈夫曼树,生成每个字符的变长编码。 - 支持对字符串进行编码和解码。 ### 实现代码(C++) ```cpp // ==================== Huffman 编码与解码 ==================== #include <map> #include <queue> #include <string> // 哈夫曼树节点 struct HuffmanNode { wchar_t ch; // 字符 int freq; // 频率 HuffmanNode* left, * right; // 左右子树 HuffmanNode(wchar_t c, int f) : ch(c), freq(f), left(nullptr), right(nullptr) {} }; // 比较函数,用于优先队列(最小堆) struct Compare { bool operator()(HuffmanNode* a, HuffmanNode* b) { return a->freq > b->freq; // 小根堆 } }; // 存储编码结果的映射表 std::map<wchar_t, std::wstring> huffmanCodeMap; std::map<std::wstring, wchar_t> huffmanDecodeMap; // 反向映射用于解码 // 构建哈夫曼树并生成编码 void BuildHuffmanCodes(const std::map<wchar_t, int>& freqMap) { std::priority_queue<HuffmanNode*, std::vector<HuffmanNode*>, Compare> pq; // 创建叶子节点并加入优先队列 for (const auto& p : freqMap) { pq.push(new HuffmanNode(p.first, p.second)); } // 构造哈夫曼树 while (pq.size() > 1) { HuffmanNode* left = pq.top(); pq.pop(); HuffmanNode* right = pq.top(); pq.pop(); HuffmanNode* merged = new HuffmanNode(L'\0', left->freq + right->freq); merged->left = left; merged->right = right; pq.push(merged); } // 根节点 HuffmanNode* root = pq.top(); // 递归生成编码 std::function<void(HuffmanNode*, std::wstring)> generateCodes; generateCodes = [&](HuffmanNode* node, std::wstring code) { if (!node) return; if (node->ch != L'\0') { // 叶子节点 huffmanCodeMap[node->ch] = code; huffmanDecodeMap[code] = node->ch; } else { generateCodes(node->left, code + L"0"); generateCodes(node->right, code + L"1"); } }; generateCodes(root, L""); // 清理内存(可选,实际应用中建议智能指针) std::function<void(HuffmanNode*)> deleteTree; deleteTree = [&](HuffmanNode* node) { if (node) { deleteTree(node->left); deleteTree(node->right); delete node; } }; deleteTree(root); // 删除动态分配的树 } // 编码函数 std::wstring HuffmanEncode(const std::wstring& text) { // 统计频率 std::map<wchar_t, int> freqMap; for (wchar_t ch : text) { freqMap[ch]++; } // 构建编码表 huffmanCodeMap.clear(); huffmanDecodeMap.clear(); BuildHuffmanCodes(freqMap); // 编码 std::wstringstream ss; for (wchar_t ch : text) { ss << huffmanCodeMap[ch]; } return ss.str(); } // 解码函数 std::wstring HuffmanDecode(const std::wstring& encoded) { std::wstring current = L"", result = L""; for (wchar_t bit : encoded) { current += bit; auto it = huffmanDecodeMap.find(current); if (it != huffmanDecodeMap.end()) { result += it->second; current = L""; } } return result; } ``` --- ## ✅ 二、添加:走迷宫(图的遍历算法) 我们模拟一个简单的二维“迷宫”,用 `DFS` 和 `BFS` 来寻找从起点到终点的路径。 ### 迷宫表示 - `0`: 可通行 - `1`: 墙壁 - 起点 `(0,0)`,终点 `(rows-1, cols-1)` ### 实现代码(DFS + BFS) ```cpp // ==================== 走迷宫(图的遍历) ==================== #include <stack> #include <deque> const int MAX_MAZE_SIZE = 10; int maze[MAX_MAZE_SIZE][MAX_MAZE_SIZE] = { {0, 1, 0, 0, 0}, {0, 1, 0, 1, 0}, {0, 0, 0, 1, 0}, {1, 1, 0, 0, 0}, {0, 0, 0, 1, 0} }; int mazeRows = 5, mazeCols = 5; struct Point { int x, y; std::wstring path; // 记录路径(例如 "→↓↓→") Point(int x, int y, const std::wstring& p = L"") : x(x), y(y), path(p) {} }; // 方向数组:上下左右 const int dx[4] = {-1, 1, 0, 0}; const int dy[4] = {0, 0, -1, 1}; const wchar_t dirChar[4] = {L'↑', L'↓', L'←', L'→'}; // 检查是否越界或碰到墙 bool IsValid(int x, int y, bool visited[][MAX_MAZE_SIZE]) { return x >= 0 && x < mazeRows && y >= 0 && y < mazeCols && !maze[x][y] && !visited[x][y]; } // 使用 DFS 寻找一条可行路径 std::wstring MazeDFS() { bool visited[MAX_MAZE_SIZE][MAX_MAZE_SIZE] = {}; std::stack<Point> stk; stk.push(Point(0, 0, L"起点")); while (!stk.empty()) { Point curr = stk.top(); stk.pop(); int x = curr.x, y = curr.y; if (x == mazeRows - 1 && y == mazeCols - 1) { return curr.path + L" → 终点"; } visited[x][y] = true; for (int i = 0; i < 4; ++i) { int nx = x + dx[i], ny = y + dy[i]; if (IsValid(nx, ny, visited)) { std::wstring newPath = curr.path + L" → " + dirChar[i]; stk.push(Point(nx, ny, newPath)); } } } return L"DFS:未找到路径"; } // 使用 BFS 寻找最短路径(按步数最少) std::wstring MazeBFS() { bool visited[MAX_MAZE_SIZE][MAX_MAZE_SIZE] = {}; std::queue<Point> q; q.push(Point(0, 0, L"起点")); visited[0][0] = true; while (!q.empty()) { Point curr = q.front(); q.pop(); int x = curr.x, y = curr.y; if (x == mazeRows - 1 && y == mazeCols - 1) { return curr.path + L" → 终点"; } for (int i = 0; i < 4; ++i) { int nx = x + dx[i], ny = y + dy[i]; if (IsValid(nx, ny, visited)) { visited[nx][ny] = true; std::wstring newPath = curr.path + L" → " + dirChar[i]; q.push(Point(nx, ny, newPath)); } } } return L"BFS:未找到路径"; } ``` --- ## ✅ 三、如何将这些功能集成进你的 GUI? 你需要在资源文件 `.rc` 中为 **主界面 IDD_DIALOG2** 添加新的按钮: ### 示例资源修改(Resource.h 和 .rc 文件) #### Resource.h 添加 ID: ```cpp #define IDC_BTN_HUFFMAN_ENCODE 1001 #define IDC_BTN_HUFFMAN_DECODE 1002 #define IDC_BTN_MAZE_DFS 1003 #define IDC_BTN_MAZE_BFS 1004 #define IDC_EDIT_OUTPUT 1005 ``` #### 在 IDD_DIALOG2 上添加控件(示例 .rc 片段): ```rc CONTROL "哈夫曼编码", IDC_BTN_HUFFMAN_ENCODE, "Button", BS_PUSHBUTTON, 10, 100, 80, 20 CONTROL "哈夫曼解码", IDC_BTN_HUFFMAN_DECODE, "Button", BS_PUSHBUTTON, 100, 100, 80, 20 CONTROL "DFS走迷宫", IDC_BTN_MAZE_DFS, "Button", BS_PUSHBUTTON, 10, 130, 80, 20 CONTROL "BFS走迷宫", IDC_BTN_MAZE_BFS, "Button", BS_PUSHBUTTON, 100, 130, 80, 20 EDITTEXT IDC_EDIT_OUTPUT, 10, 160, 200, 60, ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY ``` --- ## ✅ 四、更新 MainDlgProc 处理新按钮 ```cpp INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_COMMAND: if (wp == IDOK || wp == IDCANCEL) { EndDialog(hDlg, wp); return TRUE; } // 新增按钮处理 switch (LOWORD(wp)) { case IDC_BTN_HUFFMAN_ENCODE: { std::wstring input = L"ABACCDA"; std::wstring encoded = HuffmanEncode(input); std::wstringstream ss; ss << L"原文:" << input << L"\n编码:" << encoded << L"\n"; for (const auto& kv : huffmanCodeMap) { ss << kv.first << L"=" << kv.second << L" "; } SetWindowText(GetDlgItem(hDlg, IDC_EDIT_OUTPUT), ss.str().c_str()); return TRUE; } case IDC_BTN_HUFFMAN_DECODE: { std::wstring input = L"ABACCDA"; HuffmanEncode(input); // 先构建编码表 std::wstring encoded = HuffmanEncode(input); std::wstring decoded = HuffmanDecode(encoded); std::wstringstream ss; ss << L"解码结果:" << decoded << L"\n应等于:" << input; SetWindowText(GetDlgItem(hDlg, IDC_EDIT_OUTPUT), ss.str().c_str()); return TRUE; } case IDC_BTN_MAZE_DFS: { std::wstring result = MazeDFS(); SetWindowText(GetDlgItem(hDlg, IDC_EDIT_OUTPUT), result.c_str()); return TRUE; } case IDC_BTN_MAZE_BFS: { std::wstring result = MazeBFS(); SetWindowText(GetDlgItem(hDlg, IDC_EDIT_OUTPUT), result.c_str()); return TRUE; } } break; case WM_CLOSE: EndDialog(hDlg, IDCANCEL); return TRUE; } return FALSE; } ``` --- ## ✅ 五、最终效果说明 | 按钮 | 功能 | |------|------| | `哈夫曼编码` | 显示 "ABACCDA" 的哈夫曼编码过程和结果 | | `哈夫曼解码` | 使用已生成的编码表还原原字符串 | | `DFS走迷宫` | 输出一条从左上到右下的路径(可能不是最短) | | `BFS走迷宫` | 输出**最短步数**的路径(推荐用于寻路) | --- ## ✅ 总结 你现在拥有以下三大核心功能在一个程序中: 1. 🌐 **校园导航**(Dijkstra 最短路径) 2. 🔤 **哈夫曼编码/解码**(数据压缩基础) 3. 🧩 **走迷宫算法**(DFS/BFS 图遍历) 所有功能都通过 GUI 按钮触发,输出显示在编辑框中。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我变了_我没变

随意 。。。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值