南星&北斗 2015-07-13 09:13 采纳率: 0%
浏览 1711

Huffman树的问题,输入要统计的文件就闪掉

#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;
}

  • 写回答

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如何向数据库中添加自动生成的字段数据。