zoukankan      html  css  js  c++  java
  • haffman树

    #include<iostream>
    #include<string>
    using namespace std;
    
    int ABC[104] = { 0 };  //每个字符    权重初始为0   前大后小
    int n = 0;                
    bool  flag[104] = { false };  //已经处理过  初始false为未处理
    char text[10000];     //用text数组将a.txt里面的内容存储 
    char txt[10000];      //尽可能的大   否则二进制编码越界
    int haffman[52][50] = {-1};
    FILE *p;
    int h = 0;   //作为全局变量  作用于反编码过程 记录数组下标
    
    struct node
    {
        int data;    //仍然以数组的下标表示 字符abc
        int  rchild = -1;  //右子树
        int  lchild = -1;  //左子树
    }nodetree[103];
    
    //寻找数组中最小的值  返回下标
    int findmin()
    {
        int i = 0;
        int j = 0;
        int weight = 0;
        while (!flag[i]) i++;
        j = i;
        weight = ABC[i];
        for (; i < 104; i++)
        {
            if (flag[i] == true && weight > ABC[i])  //找出字幕出现次数大于0   且最小的
            {
                weight = ABC[i];
                j = i;
            }
        }
        flag[j] = false;     //找出的最小值下次不再参与
        return j;
    }
    
    void creat()
    {
        for (int i = 0; i < 52+n-1; i++)
        {
            nodetree[i].data = i;
        }
        //cout << "最小值排序 :" << endl;
        for (int i = 52; i <52+n-1; i++)
        {
            int a = findmin();
            int  b = findmin();
            //cout << a <<" "<< ABC[a] << endl << b <<" "<<ABC[b] << endl;
            //cout << char(a + 97-26) << endl;
            //cout << char(b + 97-26) << endl;
            nodetree[i].lchild = a;
            nodetree[i].rchild = b;
            ABC[i] = ABC[a] + ABC[b];
            flag[i] = true;
        }
        cout << endl;
        //for (int i = 52; i < 52 + n - 1; i++)
        //{
        //    cout << nodetree[i].data << " " << nodetree[i].lchild << "," << nodetree[i].rchild << endl;
        //}
    }
    
    
    int asc[50];     //用以暂时存放haffman编码
    int j = -1;    //j不会变化
    void visittree(node  tree)
    {
        if (tree.lchild == -1 && tree.rchild == -1)    //叶子节点储存字母
        {
            int i = 0; 
            
            if (tree.data < 26)
                cout << char(65 + tree.data) << "编码:";
            else
                cout << char(tree.data + 97 - 26) << "编码:";
    
            while (asc[i] != -1)
            {
                haffman[tree.data][i] = asc[i];
                cout << asc[i++];
            }
            cout << endl  ;
            return;
        }
        
        j++;
        asc[j] = 0;
        visittree(nodetree[tree.lchild]);
        asc[j] = 1;
        visittree(nodetree[tree.rchild]);
        asc[j] = -1;
        j--;
        
    }
    
    //输入根节点与数组下标  返回数组下标   haffman反编码
    int decode(node tree,int i)
    {
        if (tree.lchild == -1 && tree.rchild == -1)
        {    
            if(tree.data<26) 
                fprintf(p, "%c", tree.data +65);
            else 
                fprintf(p, "%c", tree.data + 97 - 26);
            return h;
        }
        h++;
        if (text[i] == '0')
            decode(nodetree[tree.lchild],i+1);
        else
            decode(nodetree[tree.rchild],i+1);
    }
    
    int main()
    {
        //进行初始化  
        memset(flag, false, sizeof(flag));   
        memset(asc, -1, sizeof(asc));
        memset(haffman, -1, sizeof(haffman));
        
    
        //读取已存在的文件a.txt  并把文件内容放到text数组与txt数组中  方便操作
        
        char ch;
        int i = 0;
        p = fopen("E:\a.txt", "r");
        if (p == NULL)
        {
            printf("failed to open file. ");
            exit(1);
        }
        cout << "原文中含有的英文字母是:" << endl;
        while ((ch = getc(p)) != EOF)
        {
            if (ch >= 65 && ch <= 90||ch>=97&&ch<=122)
            {
                txt[i] = ch;
                text[i++] = ch;
                cout << ch;
            }
        }
        //text[i] = '';
        //txt[i] = '';
        fclose(p);
    
    
        //输出文件中a-z,A—Z的出现的次数  以及总共出现的字母数
        cout << endl;
        i = 0;
        while (text[i] != '')//将字mu出现的次数记录作为权值写到数组ABC
        {
            if (text[i] <= 90)
                ABC[text[i++] - 65]++;
            else
                ABC[text[i++] - 97 + 26]++;
        }
        for (i = 0; i < 26; i++)
        {
            cout << "字母:" << char(i + 65) << "次数:" << ABC[i] << endl;
        }
        for (; i < 52; i++)
        {
            cout << "字母:" << char(i + 97-26) << "次数:" << ABC[i] << endl;
        }
        for (i = 0; i < 52; i++)
        {
            if (ABC[i]!=0)
            {
                n++;
                flag[i] = true;
            }
        }
        cout <<endl<< "总共的字母数量是n:" << n << endl;
    
        //创建haffman树  nodetree[n-2+52]作为根节点   
        //visittree函数将遍历所有叶子节点 并把得到的haffman编码写入二维数组haffman中
        creat();
        visittree(nodetree[n - 2+52]);
        //输出字母的haffman编码
        cout << endl << endl << endl;
        for (i = 0,j=0; i < 52; i++)
        {
            if (ABC[i] != 0)
                if (i < 26)
                {
                    cout << char(65 + i) << "编码:";
                    while (haffman[i][j] != -1)
                        cout << haffman[i][j++];
                    cout << endl;
                }
                else
                {
                    cout << char(i + 97-26) << "编码:";
                    while (haffman[i][j] != -1)
                        cout << haffman[i][j++];
                    cout << endl;
                }
            j = 0;
        }
    
        //创建b.txt  将text数组中的字母编码后写入
        i = 0;
        p = fopen("E:\b.txt", "w");
        while ((ch = text[i++])!='')
        {
            if (ch < 91)
            {
                j = 0;
                while (haffman[ch - 65][j] != -1)
                    fprintf(p, "%d", haffman[ch - 65][j++]);
            }
            else
            {
                j = 0;
                while (haffman[ch - 97+26][j] != -1)
                    fprintf(p, "%d", haffman[ch - 97+26][j++]);
            }
        }
        fclose(p);
        
        //输出b.txt中的内容 并存到text数组中
        p = fopen("E:\b.txt", "r");
        fscanf(p, "%s", text);
        printf("b.txt: %s
    ", text);
        fclose(p);
    
        //创建c.txt 对text进行反编码写c.txt   
        p = fopen("E:\c.txt", "w");
        while (text[h] != '')
        {
            decode(nodetree[52 + n - 2], h);    
        }
        fclose(p);
        cout << endl;
    
        //输出c.txt文件里面的内容 对比a.txt
        p = fopen("E:\c.txt", "r");
        fscanf(p, "%s", text);
        printf("c.txt: %s
    ", text);
        fclose(p);
    
    
        cout << endl;
        printf("a.txt: %s
    ", txt);
        cout << endl;
    
        //比较a.txt与c.txt的内容
        if (strcmp(text, txt) == 0)
            cout << "a.txt与c.txt相等,编码成功" << endl;
        else
            cout << "编码失败" << endl;
    
        getchar();
        return 0;
    }
  • 相关阅读:
    [置顶] Gridview中textbox列,按回车键或者上下键自动下移
    Java WebService入门实例
    hdu2553N皇后问题
    在SQL 脚本中进行 文件的读写
    按引用传递参数
    sencha 2.2详细说明
    [置顶] java高级工程师hibernate的知识重点
    [置顶] NYOJ117 求逆序数
    合作开发用到的几个 设计模式
    HDU1718:Rank
  • 原文地址:https://www.cnblogs.com/zhengbao/p/9175069.html
Copyright © 2011-2022 走看看