您的位置:首页 > 理论基础 > 数据结构算法

[数据结构]课程设计--哈夫曼树编码与译码

2018-01-01 23:39 369 查看
HuffmanTree.h
#pragma once

const int MaxSize = 20;//哈夫曼树最大节点数
const int Max = 10;//哈夫曼树叶子节点数

//树节点
struct HFNode
{
int weight;//结点权值
int lchild, rchild;//孩子节点下标
int parent;//双亲结点下标
};

//初始叶子结点
struct LeafNode
{
int weight;//权值
char name;//叶子字符
char code[Max+1]="0";//存放编码
};

//类
class HuffmanTree
{
public:
HuffmanTree();
~HuffmanTree();
void printtest();
void code_tree() { coding(); }
void decode_tree() { decoding(); }
private:
void init();//初始化树节点,parent=rchlid=lchild=-1
void leaf_in();//输入叶子节点信息
bool create_tree();//建树
void select(int &i1, int &i2);
void coding();//为哈夫曼树编码
void decoding();

int n = 0;//叶子节点数
HFNode hufftree[MaxSize];//储存哈夫曼树结点信息
LeafNode leaf[Max];//储存叶子节点信息
};

HuffmanTree::HuffmanTree()
{
//初始化树节点,parent=rchlid=lchild=-1
init();
//输入叶子节点信息
leaf_in();
//建树
create_tree();
}

HuffmanTree::~HuffmanTree()
{////
}


hufftree.h

#pragma once
#include"HuffmanTree.h"
#include<iostream>
#include<stack>
#include<string.h>
#include"wilson_diy.h"

//初始化结点数组值
void HuffmanTree::init() {
std::cout << "请输入叶子节点数:";
std::cin >> n;
while (n < 0 || n>Max) {
std::cout << "叶子节点数应处于[0,10],请重新输入";
std::cin >> n;
}

for (int i = 0; i < 2 * n - 1; i++) {
hufftree[i].lchild = -1;
hufftree[i].parent = -1;
hufftree[i].rchild = -1;
hufftree[i].weight = 0;
}
}

//输入叶子节点值
void HuffmanTree::leaf_in() {
for (int i = 0; i < n; i++) {
std::cout << "请输入第" << i + 1 << "个叶子节点的信息"<<std::endl;
std::cout << "名字:"; std::cin >> leaf[i].name;
std::cout << "权值:"; std::cin >> leaf[i].weight;
hufftree[i].weight=leaf[i].weight;
}
}

//建树
bool HuffmanTree::create_tree() {
int i1 = 0, i2 = 0;//两个指针,指向最小的两个值
for (int k = n; k < 2 * n - 1; k++) {
select(i1, i2);//从hufftree之中选出最小权值的无双亲结点的两项,下标为i1,i2;
//设置i1,i2双亲结点为k
hufftree[i1].parent = k;
hufftree[i2].parent = k;
//i1,i2权值相加赋值给k
hufftree[k].weight = hufftree[i1].weight + hufftree[i2].weight;
//k设置孩子结点
hufftree[k].lchild = i1;
hufftree[k].rchild = i2;
}
return true;
}

//查找hufftree权值最小两点角标
void HuffmanTree::select(int &i1, int &i2) {
int i;
bool button = true;

//从第一个开始,找到的第一个未结合点角标赋值给i1,第二个赋值给i2
for (i = 0; i < 2 * n - 1; i++) {
if (button) {
if (hufftree[i].parent == -1) {
i1 = i;
button = false;
}
}
else {
if (hufftree[i].parent == -1) {
i2 = i;
break;
}
}

}

for (i = 0; i < 2 * n - 1; i++) {
if (i2 != i && hufftree[i].parent == -1 && hufftree[i].weight > 0) {
if (hufftree[i1].weight > hufftree[i].weight) {
i1 = i;
}
}
}
for (i = 0; i < 2 * n - 1; i++) {
if (i1 != i && hufftree[i].parent == -1 && hufftree[i].weight > 0) {
if (hufftree[i2].weight > hufftree[i].weight) {
i2 = i;
}
}
}
}

//显示测试

//为哈夫曼树编码,哈夫曼树结点度为2或者0
void HuffmanTree::coding() {
int c, p,
4000
start;
char cd[Max+1];
cd
= '\0';
for (int i = 0; i < n; i++)
{
c = i;
start = n;/*倒序*/
while ((p = hufftree[c].parent) != -1)/*从叶子结点开始回溯,若这个结点是其父节点的左孩子则赋值为0,反之为1*/
{
if (hufftree[p].lchild == c)
{
cd[--start] = '0';
}
else
{
cd[--start] = '1';
}
c = p;/*回溯*/
}
strcpy_s(leaf[i].code, &cd[start]);
}
}

void HuffmanTree::decoding()
{
char s[2000];
std::cin >> s;
int a, i;
a = 2 * n - 2;/*将a的值赋为根节点所在数组序号*/
i = 0;
/*从s[0]开始直到字符串结束字符'\0'*/
while (s[i] != '\0')
{
/*从根节点开始往下,若为0则往左孩子走,为1往右孩子走*/
while ((hufftree[a].lchild != -1 && hufftree[a].rchild != -1) && s[i] != '\0')
{
if (s[i] == '0')
{
a = hufftree[a].lchild;
}
else if (s[i] == '1')
{
a = hufftree[a].rchild;
}
i++;
}
//如果按所输的码译出来的不是叶子结点则报错
if (hufftree[a].lchild == -1 && hufftree[a].rchild == -1)
{
std::cout << leaf[i].name;
a = 2 * n - 2;
}
else
{
std::cout << " error! " << std::endl;
return;
}
}
}
void HuffmanTree::printtest() {
for (int i = 0; i < 2 * n - 1; i++) {
print_tab("权值", hufftree[i].weight);
print_tab("左孩子", hufftree[i].lchild);
print_tab("右孩子", hufftree[i].rchild);
print_tab("双亲结点", hufftree[i].parent);
std::cout << std::endl;
}
print_midLine();
for (int i = 0; i < n; i++) {
std::cout << leaf[i].name<<":";
std::cout << leaf[i].code<< std::endl;
std::cout << std::endl;
}
}

wilson_diy.h

#pragma once

//输出加tab
void print_tab(char a[], int b) {
std::cout << a << ":" << b << " ";
}

//比较a,b大小,输出较小的值
int Fmin(int a, int b) {
if (a <= b)return a;
else return b;
}

void print_midLine() {
std::cout << "---------------------------------------------" << std::endl;
}


test.cpp
#include"hufftree.h"
using namespace std;
int main() {
HuffmanTree huffmantree;
huffmantree.code_tree();
system("cls");
huffmantree.printtest();

cout << "输入密码";
huffmantree.decode_tree();

system("pause");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: