#include "stdafx.h"
#include<iostream>
#include<fstream>
#include<cstring>
#include<iomanip>
using namespace std;
typedef struct huffmannode
{
char ch;
int weight;
int parent;
int lchild;
int rchild;
int index; //记录编码在数组中出现的位置
char code[40];//记录每一个字符的编码
}*huffmannodetree;
typedef struct countfreqnode
{
char nm;
int freq;
countfreqnode* next;
}*countfrelist;
//统计文件中,每个字符出现的频率
countfrelist & counthelp(char *filename){
countfrelist L;
countfreqnode *pt;
char a;
ifstream infile;
L = new countfreqnode; //统计数据存入链表中,头结点
L->next = nullptr;
infile.open(filename, ios::in | ios::_Nocreate); //打开须统计的字符文件
if (!infile) //判断打开是否正常
{
cout << "文件" << filename << "打开失败!" << endl;
exit(1);
}
while (infile.get(a)) //一个一个读入字符,直到文件尾
{
pt = L->next;
while (pt != nullptr)
{
if (pt->nm == a) //如果当前结点符号与读入符号相同,累积出现的次数
{
pt->freq++;
break;
}
pt = pt->next;
}
if (pt == nullptr) //属于新出现的符号,建立新结点,保存其出现频率
{
pt = new countfreqnode;
pt->next = nullptr;
L->next = pt;
pt->nm = a;
pt->freq = 1;
}
cout << a;
}
cout << endl;
pt = L->next; //输出每个符号出现的频率
cout << setw(10) << "符号" << setw(10) << "频率" << endl;
while ( pt!=nullptr )
{
cout << setw(10) << pt->nm << setw(10) << pt->freq << endl;
pt = pt->next;
}
infile.close();
return L; //返回保存每个符号出现频率的链表指针
}
//获取链表的长度
int ListLength(countfrelist L)
{
if (L->next == NULL)
return 0;
int length = 0;
countfreqnode *p = L->next;
while (p->next != NULL)
{
p = p->next; length++;
}
return length;
}
//选择数组中最小的两个元素
void selecttwomin(huffmannode* &HT, int len, int &s1, int &s2)
{
int i;
for (i = 0; i <=len && HT[i].parent != 0; i++);
s1 = i;
for (i = 0; i <= len; i++)
if (HT[i].parent == 0 && HT[i].weight<HT[s1].weight)
s1 = i;
for (i = 0; i <= len; i++)
if (HT[i].parent == 0 && i != s1)
break;
s2 = i;
for (i = 0; i <= len; i++)
if (HT[i].parent == 0 && i != s1 && HT[i].weight<HT[s2].weight)
s2 = i;
}
//构建Huffman树并且获取编码
huffmannodetree huffmantree(countfrelist &tm, int l){
int n,i,fmin,smin;
countfreqnode*p;
n = 2 * l - 1;
huffmannodetree ht = new huffmannode[n];
p =tm->next;
//将链表中的数据转移到数组中来
for (i = 0; i < l && p!=NULL; ++i,p=p->next)
{
ht[i].weight = p->freq;
ht[i].ch = p->nm;
ht[i].parent = ht[i].lchild = ht[i].rchild = 0;
}
for (; i < n; ++i)
{
ht[i].weight = 0;
ht[i].ch = '\0';
ht[i].parent = ht[i].lchild = ht[i].rchild = 0;
}
//建造huffman树
for (i = l; i <n; ++i)
{
selecttwomin(ht, i-1, fmin, smin);
ht[fmin].parent = i; ht[smin].parent = i;
ht[i].lchild = fmin; ht[i].rchild = smin;
ht[i].weight = ht[fmin].weight + ht[smin].weight;
}
//获取编码
for (i = 0; i < l; ++i)
{
int start = l - 1;
ht[i].code[start] = '\0';
int c, f;
for (c = i, f = ht[i].parent; f != 0; c = f, f = ht[f].parent)
{
if (ht[f].lchild == c)
ht[i].code[--start] = '0';
else ht[i].code[--start] = '1';
}
ht[i].index = start;
}
return ht;
}
//译码
void decode(huffmannodetree & ht,int l){
char infilename[20];
char outfilename[20];
char a_code[20] = "";
ifstream infile;
char a;
int c=0;
cout << "input the filename which translate" << endl;
cin >> infilename;
infile.open(infilename, ios::in | ios::_Nocreate);
if (!infile)
{
cout << "文件" << infilename << "打开失败!" << endl;
exit(1);
}
ofstream outfile;
strcat_s(outfilename, infilename);
outfile.open(outfilename, ios::out);
if (!outfile)
{
cout << "文件" << outfilename << "打开失败!" << endl;
exit(1);
}
while (infile.get(a))
{
if ('0' == a)
strcat_s(a_code, "0");
else
strcat_s(a_code, "1");
while (c < l)
{
if (0 == strcmp(a_code, &ht[c].code[ht[c].index]))
{
outfile << ht[c].ch;
strcpy_s(a_code, "");
break;
}
else
c++;
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
char filename[30];
int len;
countfrelist L;
huffmannodetree ht;
cout << "请输入待统计的文件名:";
cin >> filename;
L = counthelp(filename);
len = ListLength(L);
ht = huffmantree(L, len);
decode(ht, len);
system("pause");
return 0;
}
Huffman树的问题,输入要统计的文件就闪掉
- 写回答
- 好问题 0 提建议
- 追加酬金
- 关注问题
- 邀请回答
-
2条回答 默认 最新
- SunliyMonkey 2015-07-13 11:15关注
我看你代码有不少打印语句。
给一个建议,输入文件路径结束后,首先打印下该文件路径。确定下是否正确。
后期代码调试:
1. 使用单步调试
2. 或者在某些地方加上打印语句,看是否有输出,确定代码错误的位置解决 无用评论 打赏 举报
悬赏问题
- ¥15 ansys fluent计算闪退
- ¥15 有关wireshark抓包的问题
- ¥15 需要写计算过程,不要写代码,求解答,数据都在图上
- ¥15 向数据表用newid方式插入GUID问题
- ¥15 multisim电路设计
- ¥20 用keil,写代码解决两个问题,用库函数
- ¥50 ID中开关量采样信号通道、以及程序流程的设计
- ¥15 U-Mamba/nnunetv2固定随机数种子
- ¥15 vba使用jmail发送邮件正文里面怎么加图片
- ¥15 vb6.0如何向数据库中添加自动生成的字段数据。