输出字符串的哈弗曼编码

来源:互联网 发布:青果软件教务系统 编辑:程序博客网 时间:2024/06/07 18:00
// huffman_code.cpp : 定义控制台应用程序的入口点。
//


#include "stdafx.h"
#include <string>
#include "sstream"
#include <iostream>
using namespace std;




//定义单链表节点用于频数统计
typedef struct linknode *p;
typedef struct linknode
{
string s;
int value = 1;
p next;
}linknode, *link;


//定义树网单节点用于求解哈弗曼树(树网的定义见笔记)
typedef struct treenode *Ptotree;
typedef struct treenode
{
string s;
int value;
Ptotree left;
Ptotree right;
}treenode, *tree;
typedef struct treenetnode *PtoNode;
typedef struct treenetnode
{
PtoNode next;
tree root;
}treenetnode, *treenet;


//定义一个链表用于存储哈弗曼编码表
typedef struct codenode *Ptocode;
typedef struct codenode
{
string s1;//字符
string s2;//字符编码
Ptocode next;
}codenode, *code;


//函数声明
link count(string ss);
tree build_tree(link c);
void read(tree root, code list, string str);
string haffman_code(string ss);








int _tmain(int argc, _TCHAR* argv[])
{
cout << "请输入字符串:";
string s;
cin >> s;


string s_back;
s_back=haffman_code(s);


cout << "打印字符串编码:";
cout << s_back << endl;
return 0;
}








//统计字符串的各个字符的频数
link count(string ss)
{
link counthead = new linknode;
counthead->next = NULL;
link xlink;
int i = 1;
// istringstream iss(ss);
string s0;
int len = ss.length();
bool flag = false;
while (i <= len)
{
s0 = ss.at(i - 1);
i++;
// iss >> s0;
xlink = counthead;
while (xlink->next != NULL)
{
if (s0 == xlink->next->s)
{
xlink->next->value += 1;
flag = true;
break;
}
xlink = xlink->next;
}
if (flag == false)
{
link newlink = new linknode;
newlink->s = s0;
newlink->next = counthead->next;
counthead->next = newlink;
}
flag = false;
}
return counthead;
}


//定义一个树网根据权值的排序函数
treenet sort(treenet nethead)
{
treenet netx = nethead;
treenet nety;
tree x;//用于存储交换的树
while (netx != NULL)
{
nety = netx->next;
while ((nety != NULL))
{
if (nety->root->value < netx->root->value)
{
//满足交换条件时前后交换节点指向的树,节点位置关系不变
x = nety->root;
nety->root = netx->root;
netx->root = x;
}
nety = nety->next;
}
netx = netx->next;
}
return nethead;
}


//根据权值建立哈弗曼树
tree build_tree(link c)
{
treenet nethead = new treenetnode;
// nethead->root->s = c->s;
// nethead->root->value = c->value;
c = c->next;
nethead->next = NULL;
//先录入字符和权值
while (c != NULL)
{
treenet p = new treenetnode;
tree p_root = new treenode;
p->root = p_root;
p->root->s = c->s;
p->root->value = c->value;
p->root->left = NULL;
p->root->right = NULL;
p->next = nethead->next;
nethead->next = p;
c = c->next;
}
if (nethead->next == NULL)
{
cout << "输入的待编码内容为空" << endl;
return 0;
}
nethead = nethead->next;
//排序取前两个,结束条件是nethead->next=null
while (nethead->next != NULL)
{
nethead = sort(nethead);
tree add_tree = new treenode;
treenet min_tree = new treenetnode;
add_tree->left = nethead->root;
add_tree->right = nethead->next->root;
add_tree->value = nethead->root->value + nethead->next->root->value;
nethead->root = add_tree;//树合成
min_tree = nethead->next;
nethead->next = min_tree->next;
free(min_tree);//树删除
}
return nethead->root;
}


//遍历编码,先序递归
/*solution one*/
void read(tree root, code list, string str)
{
if (root->left != NULL)
{

str += "0"; read(root->left, list, str); str.erase(str.length() - 1, 1);
str += "1"; read(root->right, list, str); str.erase(str.length() - 1, 1);
}
else
{
code newnode = new codenode;
newnode->s1 = root->s;
newnode->s2 = str;
newnode->next = list->next;
list->next = newnode;
}
}


string haffman_code(string ss)
{
//统计频数
link linkhead = new linknode;
linkhead->next = NULL;
linkhead = count(ss);
//构建哈弗曼树
tree treehead = new treenode;
treehead->left = NULL;
treehead->right = NULL;
treehead = build_tree(linkhead);
//编写哈弗曼编码表
code listhead = new codenode;
listhead->next = NULL;
string str;
read(treehead, listhead, str);
//输出编码表
cout << "打印编码表:" << endl;
code xlist = listhead->next;
while (xlist != NULL)
{
cout << xlist->s1 << "  " << xlist->s2 << endl;
xlist = xlist->next;
}
//输出字符串对应的哈弗曼编码
int i = 0;
code listx;
string ss_back;
while (i < ss.length())
{
str = ss.at(i);
listx = listhead->next;
while (listx != NULL)
{
if (listx->s1 == str)
{
ss_back += listx->s2;
break;
}
listx = listx->next;
}
i++;
}
return ss_back;

}


原创粉丝点击