数据结构做到哈夫曼,找到了以前的代码
使用时:按1回车,输入字符串,回车,然后依次2,回车,3,回车…n,回车
#include <iostream>
#include <cstring>
#include <iomanip>
// #include "Huffman.h"
using namespace std;
char s[150]; //目标字符串
char ch[150]; //出现过的字符
int num[150]; //ch中字符对应的个数
int position[150]; //直接下标为ASCll码存储字符在num及ch中的位置
char Encoded[1024]; //存放编码过后的字符串
char ans[1024]; //存放编码再解码的字符串
int m, n;
//样例:I love data Structure, I love Computer. I will try my best to study data Structure.
//
struct HCode {
char data;
char code[100];
};
struct HNode {
int weight;
int Lchild, Rchild;
int parent;
};
class Huffman {
private:
int originalLen;
int newLen;
HNode* huffTree;
HCode* HCodeTable;
int N;
public:
void CreateHTree(int a[], int n); //建树
void CreateCodeTable(char b[], int n); //建码表
void Encode(char* s, char* d, int n, int a[]); //编码
void Decode(char* s, char* d, int n); //解码
void checkLen(); //输出编码前后长度
void PrintTree(char *s); //凹入法打印
void PreOrder(int root, int depth, char *s); //前序遍历
~Huffman();
};
void SelectMin(HNode* hTree, int n, int& i1, int& i2);
void Reverse(char c[]);
void work() {//对字符串进行统计处理
cout << "正在对字符串进行处理" << endl;
m = strlen(s), n = 0;
int pos(0);
for (int i = 0; i < m; i++) {
if (position[s[i]]) {
num[position[s[i]]] += 1;
}
else {
position[s[i]] = ++pos;
ch[pos] = s[i];
num[pos] = 1;
}
} n = pos;
for (int i = 1; i <= n; i++) {
cout << std::left << ch[i] << ":" << setw(8) << num[position[ch[i]]] << " ";
if (i % 5 == 0) puts("");
}
puts("");
}
int main() {
Huffman test;
//*************************************
int op(-1);
cout << "0:停止进程" << endl;
cout << "1:输入字串" << endl;
cout << "2:建树" << endl;
cout << "3:建表" << endl;
cout << "4:编码" << endl;
cout << "5:解码" << endl;
cout << "6:查看长度" << endl;
cout << "7:打印树" << endl;//凹入表示法
cout << "I love data Structure, I love Computer. I will try my best to study data Structure." << endl;
cout << "------------------------*" << endl;
//*************************************
while (cin >> op) {
if (!op) {
cout << "进程停止" << endl;
break;
}
if (op == 1) {//输入要进行操作的字符
cout << "输入要进行操作的字串:" << endl; getchar();
cin.getline(s, 150);
cout << "------------------------*" << endl;
work();
cout << "------------------------*" << endl;
}
if (op == 2) {//建树
cout << "---------TreeCreating" << endl;
test.CreateHTree(num + 1, n);
cout << "------------------------*" << endl;
}
if (op == 3) {//建表
test.CreateCodeTable(ch + 1, n);
cout << "------------------------*" << endl;
}
if (op == 4) {//编码
test.Encode(s, Encoded, m, position);
cout << "----------stringEncoded:" << endl << Encoded << endl;
cout << "------------------------*" << endl;
}
if (op == 5) {//解码
test.Decode(Encoded, ans, n);
cout << "----------stringDecoded:" << endl << ans << endl;
cout << "------------------------*" << endl;
}
if (op == 6) {//查看压缩前后字串长度
test.checkLen();
cout << "------------------------*" << endl;
}
if (op == 7) {
test.PrintTree(ch + 1);
cout << "------------------------*" << endl;
}
}
return 0;
}
void Huffman::CreateHTree(int a[], int n) {
N = 2 * n - 1;
huffTree = new HNode[2 * n - 1];
for (int i = 0; i < n; i++) {
huffTree[i].weight = a[i];
huffTree[i].Lchild = -1;
huffTree[i].Rchild = -1;
huffTree[i].parent = -1;
}
int li, ri;
for (int i = n; i < 2 * n - 1; i++) {
SelectMin(huffTree, i, li, ri);
huffTree[li].parent = huffTree[ri].parent = i;
huffTree[i].weight = huffTree[li].weight + huffTree[ri].weight;
huffTree[i].Lchild = li;
huffTree[i].Rchild = ri;
huffTree[i].parent = -1;
}
cout << "---------Tree Created" << endl;
}
//建表
void Huffman::CreateCodeTable(char b[], int n) {
cout << "---------CodeTable Creating..." << endl;
HCodeTable = new HCode[n];
for (int i = 0; i < n; i++) {
HCodeTable[i].data = b[i];
int k = 0, ic = i;
int ip = huffTree[i].parent;
while (ip != -1) {
if (ic == huffTree[ip].Lchild)
HCodeTable[i].code[k] = '0';
else HCodeTable[i].code[k] = '1';
k++, ic = ip;
ip = huffTree[ic].parent;
}
HCodeTable[i].code[k] = '\0';
Reverse(HCodeTable[i].code);
}
cout << "---------CodeTable Created..." << endl;
//输出码表:如下
cout << "输出码表如下:" << endl;
for (int i = 0; i < n; i++) {
cout << std::left << b[i] << ":" << setw(12) << HCodeTable[i].code;
if ((i+1) % 5 == 0) puts("");
} puts("");
}
//编码
void Huffman::Encode(char* s, char* d, int n, int position[]) {
originalLen = n;
cout << "----------Encoding..." << endl;
int pos = 0;
for (int i = 0; i < n; i++) {
int k = strlen(HCodeTable[position[s[i]] - 1].code);
for (int j = 0; j < k; j++)
d[pos++] = HCodeTable[position[s[i]] - 1].code[j];
}
newLen = pos;
}
//解码
void Huffman::Decode(char* s, char* d, int n) {
cout << "----------Decoding..." << endl;
//cout << s << endl;
while (*s != '\0') {
int k = 2 * n - 2;
while (huffTree[k].Lchild != -1) {
if (*s == '0')
k = huffTree[k].Lchild;
else k = huffTree[k].Rchild;
s++;
}
*d = HCodeTable[k].data;
d++;
}
}
Huffman::~Huffman() {
delete [] huffTree;
delete [] HCodeTable;
}
//倒置数组
void Reverse(char *c) {
int k = strlen(c);
int i = 0, j = k - 1;
while (i < j) {
swap(c[i], c[j]);
i++, j--;
}
}
//寻找最小的两个作为兄弟
void SelectMin(HNode* hTree, int n, int& i1, int& i2) {
int i;
for (i = 0; i < n; i++)
if (hTree[i].parent == -1) { i1 = i; break; }
for (++i; i < n; i++)
if (hTree[i].parent == -1) { i2 = i; break; }
if (hTree[i1].weight > hTree[i2].weight) swap(i1, i2);
for (++i; i < n; i++) {
if (hTree[i].parent == -1) {
if (hTree[i].weight < hTree[i1].weight)
i2 = i1, i1 = i;
else if (hTree[i].weight < hTree[i2].weight)
i2 = i;
}
}
}
void Huffman::checkLen() {
cout << "编码前长度:" << originalLen << " byte" << endl;
cout << "编码后长度:" << newLen << " bit (如果用bit编码)" << endl;
}
void Huffman::PreOrder(int root, int depth, char *s) {
if (huffTree[root].weight) {
for (int i = 0; i < depth*2; i++) cout << " ";
cout << std::left << setw(25-depth * 2) << setfill('-') << huffTree[root].weight;
if (huffTree[root].Lchild == -1 && huffTree[root].Rchild == -1) {
cout << s[root];
if (s[root] == ' ') cout << "(空格)";
}
cout << endl;
}
if (huffTree[root].Lchild != -1) PreOrder(huffTree[root].Lchild, depth + 1, s);
if (huffTree[root].Rchild != -1) PreOrder(huffTree[root].Rchild, depth + 1, s);
}
void Huffman::PrintTree(char *s) {
cout << "----------TreePrinting..." << endl;
PreOrder(N-1, 1, s);
}