您的位置:首页 > 编程语言 > C语言/C++

输出字符串的哈弗曼编码

2017-06-18 02:21 190 查看
// 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言 编码 控制台