c++实现求哈夫曼数及其对应的哈夫曼编码和译妈

 #include <iostream> 
 
#include<string>
using namespace std;
class HuffNode
{
public:
char c;  // 结点的字符
int weight;  // 权值
int parent, lChild, rChild; // 左右孩子指针
};
class CodeNode
{
public:
char* code;
int length;
};
class HuffTree
{
private:
int Node_cnt=0;
HuffNode* huff=NULL;
CodeNode* HuffCode= NULL;
public:
HuffTree(int n, char* c, int* weights);  // 创建Huffman树
~HuffTree(); // 析构函数
void setNode_cnt(int cnt){ Node_cnt = cnt; }
void select(int end, int& index1, int& index2); // 选出最小和次小叶子结点
void printHuffTree();
void setHuffCode();
void decoding();// 根据Huffman编码解析字符串
void printHuffCode();
int getNode_cnt(){ return Node_cnt; }

};
HuffTree::~HuffTree()
{
delete[] huff;
delete[] HuffCode;
}
void HuffTree::printHuffCode()
{
for (int i = 0; i < Node_cnt; i++)
{
cout << huff[i].c << "的哈夫曼编码为:" ;
for (int j = 0; j < HuffCode[i].length; j++)
{
cout << HuffCode[i].code[j];
}
cout << endl;
}
}
void HuffTree::setHuffCode()  // 左孩子为0,右孩子为1
{
HuffCode = new CodeNode [Node_cnt];
for (int i = 0; i < Node_cnt; i++)
{
HuffCode[i].length = 0;
int len = 0;
int son, father; // 孩子指针和双亲指针
char ch[50];  //  保留每个叶子结点Huffman码的逆序,因为是从叶子往根节点开始找
son = i;
father = huff[son].parent;
while (father != -1)
{
if (huff[father].lChild == son)  
{
ch[len++] = '0';
HuffCode[i].length++;
}
else
{
ch[len++] = '1';
HuffCode[i].length++;
}

son = father;  // 孩子指针为当前双亲指针
father = huff[father].parent;  // 双亲指针为当前双亲指针的双亲
}
HuffCode[i].code = new char[len + 1];
HuffCode[i].code[len] = '\0';
len--;
int k=0;
while (len >= 0)
{
HuffCode[i].code[k++] = ch[len--];  // 由于试探时是逆序,故Huffman编码为ch字符数组的逆序
}
}
}
HuffTree::HuffTree(int n,char* ch,int* weights){
Node_cnt = n;
huff = new HuffNode[2 * Node_cnt - 1];
for (int i = 0; i < Node_cnt; i++) // 初始化
{
huff[i].c = ch[i];
huff[i].weight = weights[i];
huff[i].lChild = -1;
huff[i].rChild = -1;
huff[i].parent = -1;
}
for (int i = Node_cnt; i < Node_cnt * 2 - 1; i++)
{
int index1 = -1, index2 = -1;
select(i - 1, index1, index2);// 选出最小和次小中间树结点索引
huff[index1].parent = i;
huff[index2].parent = i;
huff[i].weight = huff[index1].weight + huff[index2].weight;
huff[i].lChild = index1;
huff[i].rChild = index2;
huff[i].parent = -1;
}
}
void HuffTree::decoding()
{
cout << "请输入一串0/1码:" << endl;
string str;
cin >> str;
int length = str.size();
int index=2*getNode_cnt()-2;  // Huffman树的根节点在huff[]数组中的索引
for (int i = 0; i < length; i++)
{
if ((huff[index].lChild != -1) && (huff[index].rChild != -1))   // 当该结点都有左右孩子,则必然需要继续判断下一位0-1码
{
if (str[i]=='0')
{
index = huff[index].lChild;  // 结点移至当前结点的左孩子
}
else if (str[i]=='1')
{
index = huff[index].rChild;   // 结点移至当前结点的右孩子
}
}
else   // 重新回到Huffman树树根,再依次执行上面的判断
{
cout << huff[index].c;   
i--;  // i- -的目的是:保证当前输入的str[i]不被越过
index = 2 * getNode_cnt() - 2;
}
}
}
void HuffTree::printHuffTree()
{
cout << "所建哈夫曼静态链表示如下:" << endl;
cout << "位置\t" << "字符\t" << "权值\t" << "双亲\t" << "左孩子\t" << "右孩子\t" << endl;
for (int i = 0; i < Node_cnt*2-1; i++)
{
cout << i << "\t" << huff[i].c << "\t" << huff[i].weight << "\t" << huff[i].parent << "\t" << huff[i].lChild << "\t" << huff[i].rChild << endl;
}
}
void  HuffTree::select(int end, int& index1, int& index2)
{
int min1=100000,min2 = 100000;  // 设m1为最小值,m2为次小值
for (int j = 0; j <=end; j++)
{
if (huff[j].parent == -1)
{
if (huff[j].weight < min1)  // 如果当前权值比最小值小
{
index2 = index1;
index1 = j;
min2 = min1;
min1 = huff[j].weight;
}
else if (huff[j].weight < min2)  // 如果当前权值比次小值小
{
min2 = huff[j].weight;
index2 = j;
}
}
}
}


int main()
{
/****************  test  **************************/
/****************  author:刘知安  ********************/
/****************  time:2017/11/4  *******************/
int n;
cout << "请输入树叶结点的个数(小于等于1结束):" << endl;
cin >> n;
if (n < 1) return 0;
char chs[256];
int weights[256];


for (int i = 0; i < n; i++){
cout << "请输入第" << i+1 << "个字符及权值" << endl;
cin >> chs[i] >> weights[i];
}
HuffTree tree(n,chs,weights);
tree.printHuffTree();
cout << "每个字符对应的Huffman编码为:\n";
tree.setHuffCode();
tree.printHuffCode();
cout << "根据你所输入的0/1码,解析出的字符为:\n";
tree.decoding();
return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_37174526/article/details/78434589