...累了,一會更新,寫註釋,寫思路,最好能畫畫圖node
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<vector> #include<algorithm> #include<map> #include <string> using namespace std; typedef struct { int val; int weight; int parent, lchild, rchild; }HuffmanNode; static bool cmp(vector<int> a, vector<int> b) { return a[1] > b[1]; } void calculate(vector<vector<int>>& check) { FILE* file; file = fopen("a.txt", "r"); char c; while ((c = fgetc(file)) != EOF) { if (c >= 'a' && c <= 'z') { check[c - 'a'][1]++; } else if (c >= 'A' && c <= 'Z') { check[c - 'A' + 26][1]++; } else if (c == ' ') { check[52][1]++; } else if (c == ',') { check[53][1]++; } else if (c == '.') { check[54][1]++; } } sort(check.begin(), check.end(), cmp); }//統計出現字母的頻率 void initHuffmanTree(HuffmanNode* HT, int n, int m, vector<vector<int>>& check) { int j = 1; for (int i = n - 1; i >= 0; i--) { HT[j++] = {check[i][0], check[i][1],0,0,0}; } for (; j <= m; j++) { HT[j] = { 0,0,0,0,0 }; } }//初始化哈夫曼樹 void select(HuffmanNode* HT,int endLoc, int& node1, int& node2) { int min1 = INT_MAX - 1, min2 = INT_MAX; for (int i = 1; i <= endLoc; i++) { if (HT[i].parent == 0) { if (HT[i].weight < min1) { min1 = HT[i].weight; node1 = i; } else if (HT[i].weight < min2) { min2 = HT[i].weight; node2 = i; } } } }//選出兩個最小的節點 void createHuffmanTree(HuffmanNode* HT, int n, int m) { int loc; int node1, node2; for (int i = n + 1; i <= m; i++) { select(HT, i - 1, node1, node2); HT[i].lchild = node2; HT[i].rchild = node1; HT[i].weight = HT[node1].weight + HT[node2].weight; HT[node1].parent = HT[node2].parent = i; } }//創建哈夫曼樹 void encode(HuffmanNode* HT, int n, map<int, string>& huffmanCode) { int par; //父節點 int son; //子節點位置 for (int i = 1; i <= n; i++) { son = i; par = HT[i].parent; string code = ""; while (par != 0) { if (HT[par].lchild == son) { code.insert(code.begin(), '0'); } if (HT[par].rchild == son) { code.insert(code.begin(), '1'); } son = par; par = HT[par].parent; }//向上找,直到沒有parent huffmanCode[HT[i].val] = code; } }//生成哈夫曼碼 void encodeTxtToHuffmanCode(map<int, string>& huffmanCode) { FILE* readFile = fopen("a.txt", "r"); FILE* writeFile = fopen("b.txt", "w"); char c = fgetc(readFile); while (c != EOF) { int i; if (c >= 'a' && c <= 'z') { i = c - 'a'; } else if (c >= 'A' && c <= 'Z') { i = c - 'A' + 26; } else if (c == ' ') { i = 52; } else if (c == ',') { i = 53; } else if (c == '.') { i = 54; } for (int j = 0; j < huffmanCode[i].size(); j++) { fputc(huffmanCode[i][j], writeFile); } c = fgetc(readFile); } fclose(readFile); fclose(writeFile); } void decode(HuffmanNode* HT, int n) { FILE* readFile = fopen("b.txt", "r"); FILE* writeFile = fopen("c.txt", "w"); char c = fgetc(readFile); int i = 2 * n - 1; while (c != EOF) { if (c == '0') { i = HT[i].lchild; } else if (c == '1') { i = HT[i].rchild; } if (HT[i].lchild == 0 || HT[i].rchild == 0) { char c; if (HT[i].val >= 0 && HT[i].val <= 25) { c = 'a' + HT[i].val; } else if (HT[i].val >= 26 && HT[i].val <= 51) { c = 'A' + HT[i].val - 26; } else if (HT[i].val == 52) { c = ' '; } else if (HT[i].val == 53) { c = ','; } else if (HT[i].val == 54) { c = '.'; } fputc(c, writeFile); i = 2 * n - 1; } c = fgetc(readFile); } fclose(readFile); fclose(writeFile); }//哈夫曼碼翻譯成文章 int main() { vector<vector<int>> check(55,vector<int>(2,0)); for (int i = 0; i < check.size(); i++) { check[i][0] = i; } calculate(check); int n = 0; //葉子個數(出現的字母個數) for (int i = 0; i < check.size(); i++) { if (check[i][1] != 0) n++; } int m = 2 * n - 1; //Huffman節點 HuffmanNode* HT; HT = (HuffmanNode*)malloc((m + 1) * sizeof(HuffmanNode)); //第0個節點不用 initHuffmanTree(HT, n, m, check); createHuffmanTree(HT, n, m); /*for (int i = 1; i <= m; i++) { cout << HT[i].val << " " << HT[i].weight << " " << HT[i].parent << " " << HT[i].lchild << " " << HT[i].rchild << endl; }*/ map<int, string> huffmanCode; encode(HT, n, huffmanCode); /*for (auto x : huffmanCode) { cout << x.first << " " << x.second << endl; }*/ encodeTxtToHuffmanCode(huffmanCode); decode(HT, n); }