c++哈夫曼编码与译码c++哈夫曼编码与译码
#include
#include //系统自带的字符串库函数 using namespace std;
struct Node
{ char data; // 节点数据域为字符型
Node *next;
Node(){ next = NULL;};
Node(char item, Node *link = NULL){ data = item; next = link;};
};
class LinkList
{//仅保留几个用得到的成员函数 protected:
Node *...
c++哈夫曼编码与译码
#include
#include //系统自带的字符串库 using namespace std;
struct Node
{ char data; // 节点数据域为字符型
Node *next;
Node(){ next = NULL;};
Node(char item, Node *link = NULL){ data = item; next = link;};
};
class LinkList
{//仅保留几个用得到的成员函数 protected:
Node *head;
Node *curPtr;
int count,curPosition;
Node *GetElemPtr(int position); // 返回指向第position个结点的指针
public:
LinkList();
int Length() const;
bool Empty() const;
void Traverse() ;
void Insert(int position, const char &e);
char GetElem(int position) ;
};
Node * LinkList::GetElemPtr(int position) {
if (curPosition > position)
{ curPosition = 0;
curPtr = head;
}
for (; curPosition < position; curPosition++)
curPtr = curPtr->next;
return curPtr;
}
char LinkList::GetElem(int position) { Node *tmr;
tmpPtr = GetElemPtr(position);
char e = tmpPtr->data;
return e;
}
LinkList::LinkList()
{
head = new Node; // 构造头指针,带头结点的链表
curPtr = head;
curPosition =0;
count = 0;
}
int LinkList::Length() const
{
return count;
}
bool LinkList::Empty() const
{
return head->next == NULL;
}
void LinkList::Traverse()
{
for (Node *tmpPtr = head->next; tmpPtr != NULL; tmpPtr = tmpPtr->next)
{
cout<<(tmpPtr->data);
}
}
void LinkList::Insert(int position, const char &e)
{ Node *tmpPtr;
tmpPtr = GetElemPtr(position - 1);
Node *newPtr;
newPtr = new Node(e, tmpPtr->next);
tmpPtr->next = newPtr;
curPosition = position;
curPtr = newPtr;
count++;
}
// 哈夫曼树结点类
struct HuffmanTreeNode
{
int weight;
unsigned int parent, leftChild, rightChild; // 双亲,左右孩子域
HuffmanTreeNode();
HuffmanTreeNode(int w, int p = 0, int lChild = 0, int rChild = 0);
};
HuffmanTreeNode::HuffmanTreeNode()
{
parent = leftChild = rightChild = 0;
}
HuffmanTreeNode::HuffmanTreeNode(int w, int p, int lChild, int rChild) // 右孩子
{
weight = w; // 权
parent = p; // 双亲
leftChild = lChild; // 左孩子
rightChild = rChild; // 右孩子
}
class HuffmanTree
{
protected:
//
HuffmanTreeNode *nodes; // 存储结点信息,nodes[0]未用
char *LeafChars; // 叶结点字符信息,LeafChars[0]未用
string *LeafCharCodes; // 叶结点字符编码信息,LeafCharCodes[0]未用
int curPos; // 译码时从根结点到叶结点路径的当前结点
int num; // 叶结点个数
// 辅助函数:
void Select(int cur, int &r1, int &r2); // nodes[1 ~ cur]中选择双亲为0,权值最小的两个结点
r1,r2
void CreatHuffmanTree(char ch[], int w[], int n);
public:
HuffmanTree(char ch[], int w[], int n); // 由字符,权值和字符个数构造哈夫曼树
virtual ~HuffmanTree(); // 析构函数
string Encode(char ch); // 编码
LinkList Decode(string strCode); // 译码
};
void HuffmanTree::Select(int cur, int &r1, int &r2) {
r1 = r2 = 0; // 0表示空结点
for (int pos = 1; pos <= cur; pos++)
{
if (nodes[pos].parent != 0) continue; // 只处理双亲为0的结点
if (r1 == 0)
{
r1 = pos;
}
else if (r2 == 0)
{
r2 = pos;
}
else if (nodes[pos].weight < nodes[r1].weight)
{
r1 = pos;
}
else if (nodes[pos].weight < nodes[r2].weight)
{
r2 = pos;
}
}
}
void HuffmanTree::CreatHuffmanTree(char ch[], int w[], int n) {
num = n; // 叶结点个数
int m = 2 * n - 1; // 结点个数
nodes = new HuffmanTreeNode[m + 1]; // nodes[0]未用
LeafChars = new char[n + 1]; // LeafChars[0]未用
LeafCharCodes = new string[n + 1]; // LeafCharCodes[0]未用
int pos; // 临时变量
for (pos = 1; pos <= n; pos++)
{ // 存储叶结点信息
nodes[pos].weight = w[pos - 1]; // 权值
LeafChars[pos] = ch[pos - 1]; // 字符
}
for (pos = n + 1; pos <= m; pos++)
{ // 建立哈夫曼树
int r1, r2;
Select(pos - 1, r1, r2);
nodes[r1].parent = nodes[r2].parent = pos; // r1,r2双亲为pos
nodes[pos].leftChild = r1; // r1为pos的左孩子
nodes[pos].rightChild = r2; // r2为pos的右孩子
nodes[pos].weight = nodes[r1].weight + nodes[r2].weight;//pos的权为r1,r2的权值之和
}
for (pos = 1; pos <= n; pos++)
{ // 求n个叶结点字符的编码
LinkList charCode; // 暂存叶结点字符编码信息
for (unsigned int child = pos, parent = nodes[child].parent; parent != 0;
child = parent, parent = nodes[child].parent)
{ if (nodes[parent].leftChild == child) charCode.Insert(1,'0');
else charCode.Insert(1,'1');;
}
for(int i=1;i<=charCode.Length();i++)
LeafCharCodes[pos].append(1, charCode.GetElem(i));//没有直接可以从链表为字符串赋
值的函数,只能一个字符一个字符的追加过去
}
curPos = m;
}
HuffmanTree::HuffmanTree(char ch[],int w[], int n)
{
CreatHuffmanTree(ch, w, n);
}
HuffmanTree::~HuffmanTree()
{
if (nodes != NULL) delete []nodes; // 释放结点信息
if (LeafChars != NULL) delete []LeafChars; // 释放叶结点字符信息
if (LeafCharCodes != NULL) delete []LeafCharCodes; // 释放叶结点字符编码信息
}
string HuffmanTree::Encode(char ch)
{
for (int pos = 1; pos <= num; pos++)
{ if (LeafChars[pos] == ch) return LeafCharCodes[pos];// 找到字符,得到编码
}
}
LinkList HuffmanTree::Decode(string strCode)
// 操作结果:对编码串strCode进行译码,返回编码前的字符序列 {
LinkList charList; // 编码前的字符序列
for (int pos = 0; pos < strCode.length(); pos++)
{ // 处理每位编码
if (strCode[pos] == '0') curPos = nodes[curPos].leftChild; // '0'表示左分支
else curPos = nodes[curPos].rightChild; // '1'表示左分支
if (nodes[curPos].leftChild == 0 && nodes[curPos].rightChild == 0)
{ // 译码时从根结点到叶结点路径的当前结点为叶结点
charList.Insert(charList.Length() + 1, LeafChars[curPos]);
curPos = 2 * num - 1;
}
}
return charList;
}
int main(void)
{ char *ch;
int *w,n,i;
cout<<"输入字符集中字符的个数:"<>n;
ch=new char[n];
w=new int[n];
cout<<"输入字符集中的字符:"<>ch[i];
cout<<"输入字符集中的字符的权值:"<>w[i];
HuffmanTree hmTree(ch, w, n);
string strText,strCode;
cout<<"请输入要编码的字符串";
cin>>strText;
cout << "文本串" << strText.c_str()<< "编码为:";
for (int pos = 0; pos < strText.length(); pos++)
{
string strTmp = hmTree.Encode(strText[pos]);
cout << strTmp.c_str();
}
cout << endl;
system("PAUSE");
cout<<"请输入要译码的二进制串";
cin>>strCode;
cout << "编码串" << strCode.c_str()<< "译码为:";
LinkList lkText = hmTree.Decode(strCode);
lkText.Traverse();
system("PAUSE");
return 0;
}
本文档为【c++哈夫曼编码与译码】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑,
图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。