实验五 哈夫曼编码算法的实现
点击查看代码
#include <iostream>
#include <fstream>
#include <queue>
#include <map>
#include <vector>
#include <string>
#include <bitset>
#include <sstream>
using namespace std;struct Huffm {char chrs; int fre; Huffm* left;Huffm* right;Huffm(char c, int freq) : chrs(c), fre(freq), left(nullptr), right(nullptr) {}Huffm(Huffm* l, Huffm* r) : chrs('\0'), fre(l->fre + r->fre), left(l), right(r) {}
};struct Compare {bool operator()(Huffm* lhs, Huffm* rhs) {return lhs->fre > rhs->fre;}
};// 生成哈夫曼编码
void g_Huffm(Huffm* root, const string& str, map<char, string>& hu) {if (!root) return;if (!root->left && !root->right)hu[root->chrs] = str;g_Huffm(root->left, str + "0", hu);g_Huffm(root->right, str + "1", hu);
}// 统计字符频率
map<char, int> c_Chr(const string& filename) {ifstream file(filename);map<char, int> fre_Map;char c;if (!file.is_open()) {cerr << "无法打开文件 " << filename << endl;exit(EXIT_FAILURE); }while (file.get(c))fre_Map[c]++;return fre_Map;
}// 创建哈夫曼树
Huffm* huffmtree(const map<char, int>& fremap) {priority_queue<Huffm*, vector<Huffm*>, Compare> minHeap;for (const auto& pair : fremap) minHeap.push(new Huffm(pair.first, pair.second));while (minHeap.size() > 1) {Huffm* left = minHeap.top(); minHeap.pop();Huffm* right = minHeap.top(); minHeap.pop();Huffm* merged = new Huffm(left, right);minHeap.push(merged);}return minHeap.top();
}// 将编码写入文件
void w_HuffmF(const map<char, string>& huff, const string& filename) {ofstream outFile(filename);if (!outFile.is_open()) {cerr << "无法打开文件 " << filename << endl;exit(EXIT_FAILURE); }for (const auto& pair : huff)outFile << pair.first << ": " << pair.second << endl;
}// 对文件内容进行哈夫曼编码
void en_File(const string& s_File, const map<char, string>& huff, const string& r_File) {ifstream inFile(s_File);ofstream outFile(r_File, ios::binary); stringstream enText;char c;if (!inFile.is_open()) {cerr << "无法打开文件 " << s_File << endl;exit(EXIT_FAILURE); // 如果无法打开源文件,则退出程序}while (inFile.get(c))if (huff.find(c) != huff.end()_enText << huff.at(c); else {cerr << "字符 " << c << " 未在哈夫曼编码表中找到" << endl;exit(EXIT_FAILURE);}string bitString = enText.str();while (bitString.size() % 8 != 0)bitString += '0'; for (size_t i = 0; i < bitString.size(); i += 8) {bitset<8> byte(bitString.substr(i, 8)); outFile.put(static_cast<char>(byte.to_ulong())); }
}int main() {string s_File = "SourceFile.txt"; string codeFile = "Code.txt"; string resultFile = "ResultFile.txt"; map<char, int> fre_Map = c_Chr(s_File);if (fre_Map.empty()) {cerr << "源文件中没有有效字符!" << endl;return EXIT_FAILURE;}Huffm* root = huffmtree(fre_Map);map<char, string> huffmanCodes;g_Huffm(root, "", huffmanCodes);w_HuffmF(huffmanCodes, codeFile);en_File(s_File, huffmanCodes, resultFile);cout << "哈夫曼编码系统已完成!" << endl;return 0;
点击查看代码
#include <iostream>
#include <vector>
#include <string>
#include <climits>
#include <map>
#include <fstream>
#include <algorithm>
using namespace std;
const int INF = INT_MAX;// 邻接矩阵表示图
class Graph {
public:vector<vector<int>> adjMatrix; vector<string> places; map<string, string> placesInfo; Graph(int n) {adjMatrix.resize(n, vector<int>(n, INF)); // 初始化邻接矩阵为无穷大for (int i = 0; i < n; i++) {adjMatrix[i][i] = 0; }}void addEdge(int u, int v, int weight) {adjMatrix[u][v] = weight;adjMatrix[v][u] = weight;}void addPlaceInfo(const string& place, const string& info) {placesInfo[place] = info;}void getPlaceInfo(const string& place) {if (placesInfo.find(place) != placesInfo.end()) {cout << place << ": " << placesInfo[place] << endl;}else {cout << "景点未找到!" << endl;}}// Dijkstra 算法计算最短路径void dijkstra(int start, int end) {int n = places.size();vector<int> dist(n, INF);vector<int> prev(n, -1);vector<bool> visited(n, false);dist[start] = 0;for (int i = 0; i < n; i++) {int u = -1;for (int j = 0; j < n; j++) {if (!visited[j] && (u == -1 || dist[j] < dist[u])) {u = j;}}if (dist[u] == INF) break;visited[u] = true;for (int v = 0; v < n; v++) {if (adjMatrix[u][v] != INF && dist[u] + adjMatrix[u][v] < dist[v]) {dist[v] = dist[u] + adjMatrix[u][v];prev[v] = u;}}}// 追溯路径vector<string> path;for (int u = end; u != -1; u = prev[u]) {path.push_back(places[u]);}reverse(path.begin(), path.end());if (dist[end] == INF) {cout << "没有路径从 " << places[start] << " 到 " << places[end] << endl;}else {cout << "从 " << places[start] << " 到 " << places[end] << " 的最短路径是:";for (const string& p : path) {cout << p << " ";}cout << "路径长度:" << dist[end] << endl;}}
};void readGraphFromFile(const string& filename, Graph& graph) {ifstream file(filename);if (!file.is_open()) {cerr << "文件打开失败!" << endl;return;}string u, v;int weight;map<string, int> placeIndex;vector<string> places;while (file >> u >> v >> weight) {if (u == "0") break;if (placeIndex.find(u) == placeIndex.end()) {placeIndex[u] = places.size();places.push_back(u);}if (placeIndex.find(v) == placeIndex.end()) {placeIndex[v] = places.size();places.push_back(v);}int uIndex = placeIndex[u];int vIndex = placeIndex[v];graph.addEdge(uIndex, vIndex, weight);}// 读取景点介绍信息for (const auto& place : places) {string info;cout << "请输入景点 '" << place << "' 的介绍:";cin.ignore();getline(cin, info);graph.addPlaceInfo(place, info);graph.places.push_back(place);}file.close();
}int main() {Graph graph(10);readGraphFromFile("graph.txt", graph);while (true) {cout << "\n菜单:" << endl;cout << "1. 查询景点信息" << endl;cout << "2. 查询最短路径" << endl;cout << "3. 查看所有景点" << endl;cout << "4. 退出" << endl;cout << "请输入选择:";int choice;cin >> choice;if (choice == 1) {string place;cout << "请输入景点名称:";cin.ignore();getline(cin, place);graph.getPlaceInfo(place);}else if (choice == 2) {string start, end;cout << "请输入起始景点:";cin.ignore();getline(cin, start);cout << "请输入目的景点:";getline(cin, end);int startIndex = find(graph.places.begin(), graph.places.end(), start) - graph.places.begin();int endIndex = find(graph.places.begin(), graph.places.end(), end) - graph.places.begin();graph.dijkstra(startIndex, endIndex);}else if (choice == 3) {cout << "所有景点:\n";for (const auto& place : graph.places) {cout << place << endl;}}else {cout << "祝你玩得开心!" << endl;break;}}return 0;
}
点击查看代码
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;struct stu {string name;long long st;double test;
}k[10000];bool pan(stu a, stu b) { return a.st < b.st; } //sort函数的排序设定int chu() { //初始化int i = 0;cout << "请按姓名、学号、成绩的顺序输入成绩:\n";while (1) {cout << "姓名(输入\"#\"结束): ";cin >> k[i].name;if (k[i].name == "#") break;cout << "学号: ";cin >> k[i].st; cout << "成绩: ";cin >> k[i++].test; cout << endl;}sort(k, k + i,pan); //按学号排序return i;
}void find1(string na,int n) { /姓名查找for(int i=0;i<n;i++)if (k[i].name == na) {cout << "查找成功!信息如下:\n";cout << "姓名:" << k[i].name << endl;cout << "学号:" << k[i].st << endl;cout << "成绩:" << k[i].test<< endl << endl;return;}cout << "查无此人!" << endl << endl;
}void find2(long long te,int n) { //学号查找int l = 0, r = n - 1;while (l <= r) {int mid = l + r >> 1;if (k[mid].st<te) l = mid+1;else r = mid - 1;}if (k[l].st == te) {cout << "查找成功!信息如下:\n";cout << "姓名:" << k[l].name << endl;cout << "学号:" << k[l].st << endl;cout << "成绩:" << k[l].test << endl << endl;return;}cout << "查无此人!" << endl << endl;
}int main() {int n=chu();//for (int i = 0; i < n; i++) cout << k[i].name << ' ';int m;while (1) {cout << "请输入1(按姓名查找)或 2 (按学号查找),其他(退出)\n";cin >> m;if (m == 1) {string str;cout << "请输入要查找的姓名: ";cin >> str;find1(str,n);}else if (m == 2) {long long s;cout << "请输入要查找的学号: ";cin >> s;find2(s,n);} else {cout << "再见!";break;} }return 0;
}
点击查看代码
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;struct stu {string name;long long st;double test;
}k[10000], k2[10000];bool pan(stu a, stu b) { return a.st < b.st; }int chu() {int i = 0;cout << "请按姓名、学号、成绩的顺序输入成绩:\n";while (1) {cout << "姓名(输入\"#\"结束): ";cin >> k[i].name;if (k[i].name == "#") break;cout << "学号: ";cin >> k[i].st;cout << "成绩: ";cin >> k[i].test; cout << endl;k2[i] = k[i]; i++;}//sort(k, k + i, pan);return i;
}void xier(int len) {int gap = len / 2;for (; gap > 0; gap /= 2) {for (int i = gap; i < len; i++) {stu cur = k[i]; int j;for (j = i - gap; j >= 0 && k[j].st > cur.st; j -= gap)k[j + gap] = k[j];k[j + gap] = cur;}}
}void qui(int l, int r)
{if (l >= r) return;int i = l - 1, j = r + 1, x = k[l + r >> 1].test;while (i < j){do i++; while (k[i].test < x);do j--; while (k[j].test > x);if (i < j) swap(k[i], k[j]);}qui(l, j), qui(j + 1, r);
}
void printfs(stu p[], int n) {printf("%5s%15s%5s\n", "姓名", "学号", "成绩");for (int i = 0; i < n; i++) {cout << p[i].name;printf("%15lld%5.1lf\n", p[i].st, p[i].test);}
}int main() {int i = chu();int a;while (1) {cout << "请进行你的操作:\n";cout << "1:按原始成绩单输出\n";cout << "2:按学号输出\n";cout << "3:按成绩排序输出\n";cout << "其他:退出\n";cin >> a;switch (a){case 1:printfs(k2, i); break;case 2:xier(i);printfs(k, i); break;case 3:qui(0, i);printfs(k, i); break;default:break;}if (a < 1 || a>3) break;}return 0;
}