Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/3: Рейтинг темы: голосов - 3, средняя оценка - 5.00
Oksi0601
0 / 0 / 0
Регистрация: 07.06.2015
Сообщений: 5
1

Метод Хаффмана

15.05.2017, 10:06. Просмотров 605. Ответов 2
Метки нет (Все метки)

Есть метод Хаффмана, но при выполнение в кодировании где-то добавляються переносы строк и из-за этого происходит неправильная кодировка.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
    #include <iostream>
    #include <vector>
    #include <map>
    #include <list>
    #include <fstream>
    using namespace std;
    
    class Node
    {
        public:
        int number; //число
        char symbol; //символ
        Node *left, *right;
    
        Node()
        {
            left=right=NULL;
        }
    
        Node(Node *L, Node *R)
        {
            left =  L;
            right = R;
            number = L->number + R->number;
        }
    };
    
    //перегрузка параметров l, r
    struct MyCompare
    {
        bool operator()(const Node* l, const Node* r) const
        {
            // возвращаем True, если параметр l < r
            return l->number < r->number;
        }
    };
    
    vector<bool> code;
    map<char,vector<bool> > table;
    
    void BuildTable(Node *root)
    {
        if (root->left!=NULL)
        {
            code.push_back(0);
            BuildTable(root->left);
        }
    
        if (root->right!=NULL)
        {
            code.push_back(1);
            BuildTable(root->right);
        }
        //если нашли букву (если буква существует)
        if (root->left==NULL && root->right==NULL)
            table[root->symbol]=code; //ассоциируем эту букву с кодом
    
        code.pop_back();
    }
    
    int main (int argc, char *argv[])
    {
        setlocale(LC_ALL,"Russian");
    
        if(argc != 4)
        {
            cout << "\n         -----------------------------------------------" << endl;
            cout << "        |             Лабораторная работа №2            |" << endl;
            cout << "        |         Сжатие данных: метод Хаффмана         |" << endl;
            cout << "         -----------------------------------------------" << endl;
            cout << " ---------------------------------------------------------------" << endl;
            cout << "| Инструкция:                                                   |" << endl;
            cout << "|                                                               |" << endl;
            cout << "|\t [lab2] +                                               |" << endl;
            cout << "|                                                               |" << endl;
            cout << "|\t [входной_файл.расширение] +                            |" << endl;
            cout << "|\t [кодируемый_файл.расширение] +                         |" << endl;
            cout << "|\t [декодируемый_файл.расширение]                         |" << endl;
            cout << "|                                                               |" << endl;
            cout << " ---------------------------------------------------------------" << endl;
        }
        else
        {
            // считаем частоты символов
            ifstream ifile(argv[1], ios::out | ios::binary);
            map<char,int> m;
            while (1)
            {
                int c = ifile.get();
                if (c == -1)
                    break;
                m[(char)c]++;
            }
    
            //while (!f.eof())
            //{ char c = f.get();
            //   m[c]++;}
    
            // записываем начальные узлы в список list
            list<Node*> t;
            for( map<char,int>::iterator itr=m.begin(); itr!=m.end(); ++itr)
            {
                Node *p = new Node;
                p->symbol = itr->first;
                p->number = itr->second;
                t.push_back(p);
            }
    
            //  создаем дерево
            while (t.size()!=1)
            {
                t.sort(MyCompare());               //сортируем list
                Node *SonL = t.front();            //берем первый элемент и присваем первому элементу который идет в списке
                t.pop_front();                     //удаляем первый элемент, на его место становиться второй
                Node *SonR = t.front();            //который стал дальше первым - становиться правым сыном
                t.pop_front();
    
                Node *parent = new Node(SonL,SonR);
                t.push_back(parent);
            }
    
            Node *root = t.front();   //root - указатель на вершину дерева
            // создаем пары 'символ-код':
            BuildTable(root);
            ifile.clear(); ifile.seekg(0); // перемещаем указатель снова в начало файла
    
            ofstream ofile(argv[2], ios::out | ios::binary);
            int count=0;
            char buf=0;
    
            while (!ifile.eof())
            {
                char c = ifile.get();
                vector<bool> x = table[c];
                for(int n=0; n < x.size(); n++)
                {
                    buf = buf | x[n]<<(7-count);
                    count++;
                    if (count==8)
                    {
                        count=0;
                        ofile << buf;
                        buf=0;
                    }
                }
            }
    
            ifile.close();
            ofile.close();
    
            cout << "Сжатие выполнено..." << endl;
    
            ifstream iifile(argv[2], ios::in | ios::binary);
            ofstream oofile(argv[3]);
    
            Node *p = root;
            count = 0;
            char byte;
            byte = iifile.get();
            while(!iifile.eof())
            {
                bool b = byte & (1 << (7-count) ) ;
                if (b)
                    p=p->right;
                else
                    p=p->left;
                if (p->left==NULL && p->right==NULL)
                {
                    oofile << p->symbol;
                    p = root;
                }
                count++;
                if (count == 8)
                {
                    count = 0;
                    byte = iifile.get();
                }
            }
            iifile.close();
            oofile.close();
            cout << "Файл разархивировано..." << endl;
        }
        return 0;
    }
Текст кодируемого файла:
qwqwqwqwqwqwqqqqqqqqqq \n
\n
\n
\n
\n
\n
\n
\\тут заканчиваться переносы строки.
Раскодирует строку по тексту правильно до добавляет больше в 2 раза переносов. Ну и отображается конечно это все на размерах:
1.txt - кодируемый файл
2.huf - закодированый
3.txt - декодированый

http://www.cyberforum.ru/attachment....1&d=1494831812

Буду очень благодарна, есть кто поможет решить проблему.
0
Миниатюры
Метод Хаффмана  
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.05.2017, 10:06
Ответы с готовыми решениями:

Метод хаффмана (Помогите адаптировать под задание)
Может уже кто-то знаком с этим методом кодирования букв. Помогите адаптировать...

СЛАУ. Метод обратной матрицы, метод Гаусса, метод Крамера, метод Зейделя
Помогите ребят. Не могу построить алгоритмы для этих методов Язык C++

Метод медиан из трех элементов VS улучшенный быстрый метод сортировки(метод Бентли-Макилроя)
Здравствуйте! Дали весьма интересное задание. Сравнить два вышеуказанных метода...

Мой код - метод бисекции, метод секущих (метод хорд)
Всем привет!!! Изучаем в институте С++. Сделал код, и там, и там одна и та же...

кодирование хаффмана
здравствуйте! я пишу программу сжатия jpeg. написала код для кодирования...

2
Antikl
с++
297 / 290 / 154
Регистрация: 15.07.2015
Сообщений: 1,556
Завершенные тесты: 6
15.05.2017, 10:43 2
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
//comressor
//Код Хаффмана
#include <iostream>
#include <fstream>
#include <map>
#include <vector>
using namespace std;
 
int main()
{
    int weight[0x100];
    for (auto &i: weight)
        i = 0;
    {
        ifstream f("../feinman.html");
        while (!f.eof())
        {
            unsigned char ch;
            f.read((char *)&ch, sizeof(ch));
            ++weight[ch];
        }
    }
    multimap<int /*weight*/, int /* index in the tree */> sortedWeight;
    struct Node
    {
        char ch;
        int parent;
        int zero;
        int one;
        bool branch;
    };
    vector<Node> tree;
    map<char, int> charMap;
    for (size_t i = 0; i < 0x100; ++i)
    {
        if (weight[i] > 0)
        {
            tree.push_back(Node{(char)i, -1, -1, -1, false});
            charMap[i] = tree.size() - 1;
            sortedWeight.insert(make_pair(weight[i], tree.size() - 1));
        }
    }
    while (sortedWeight.size() > 1)
    {
        int w0 = begin(sortedWeight)->first;
        int n0 = begin(sortedWeight)->second;
        sortedWeight.erase(begin(sortedWeight));
        int w1 = begin(sortedWeight)->first;
        int n1 = begin(sortedWeight)->second;
        sortedWeight.erase(begin(sortedWeight));
        tree.push_back(Node{'\0', -1, n0, n1, false});
        tree[n0].parent = tree.size() - 1;
        tree[n0].branch = false;
        tree[n1].parent = tree.size() - 1;
        tree[n1].branch = true;
        sortedWeight.insert(make_pair(w0 + w1, tree.size() - 1));
    }
    vector<bool> data;
    {
        ifstream f("../feinman.html");
        while (!f.eof())
        {
            unsigned char ch;
            f.read((char *)&ch, sizeof(ch));
            auto n = tree[charMap[ch]];
            vector<bool> compressedChar;
            while (n.parent != -1)
            {
                compressedChar.push_back(n.branch);
                n = tree[n.parent];
            }
            data.insert(end(data), compressedChar.rbegin(), compressedChar.rend());
        }
    }
    ofstream f("../lesson48.huff");
    int treeSize = tree.size();
    f.write((char *)&treeSize, sizeof(treeSize));
    for (auto i: tree)
        f.write((char *)&i, sizeof(i));
    for (size_t i = 0; i <= data.size() / 8; ++i)
    {
        unsigned char ch = 0;
        for (int j = 0; j < 8; ++j)
            if (data[i * 8 + j])
                ch |= (1 << j);
        f.write((char *)&ch, sizeof(ch));
    }
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//decomressor
#include <vector>
#include <fstream>
#include <iostream>
using namespace std;
 
int main()
{
    struct Node
    {
        char ch;
        int parent;
        int zero;
        int one;
        bool branch;
    };
    vector<Node> tree;
 
    ifstream f("../lesson48.huff");
    int treeSize;
    f.read((char *)&treeSize, sizeof(treeSize));
    for (int i = 0; i < treeSize; ++i)
    {
        Node n;
        f.read((char *)&n, sizeof(n));
        tree.push_back(n);
    }
    vector<bool> data;
    while (!f.eof())
    {
        unsigned char ch;
        f.read((char *)&ch, sizeof(ch));
        for (int i = 0; i < 8; ++i)
            data.push_back((ch & (1 << i)) != 0);
    }
    auto n = tree.size() - 1;
    for (auto i: data)
    {
        if (i)
            n = tree[n].one;
        else
            n = tree[n].zero;
        if (tree[n].one == -1)
        {
            cout << tree[n].ch;
            n = tree.size() - 1;
        }
    }
}
0
nonedark2008
1061 / 793 / 223
Регистрация: 28.07.2012
Сообщений: 2,213
15.05.2017, 11:13 3
Oksi0601,
1) Крешится на code.pop_back();
2) Наверно в бинарном режиме стоит открывать все файлы, а не только 2 из 3х.
3) Нужно обрабатывать краевой случай, когда у тебя в буфере, скажем, 3 бита, а файл уже закончился.
1
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.05.2017, 11:13

Алгоритм Хаффмана
Решил разобраться с этим алгоритмом, собственно он состоит из нескольких из...

Псевдоалгоритм Хаффмана
есть алгоритм n – количество символов исходного алфавита P – массив...

кодировка Хаффмана
Дорогие программисты. Вот был написан код &quot;кодировка Хаффмана&quot;, и тут мы вводим...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru