Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Oksi0601
0 / 0 / 0
Регистрация: 07.06.2015
Сообщений: 5
#1

Метод Хаффмана - C++

15.05.2017, 10:06. Просмотров 525. Ответов 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
Миниатюры
Метод Хаффмана  
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.05.2017, 10:06
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Метод Хаффмана (C++):

Метод хаффмана (Помогите адаптировать под задание) - C++
Может уже кто-то знаком с этим методом кодирования букв. Помогите адаптировать код представленный ниже к заданию (В задании другой язык, но...

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

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

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

Псевдоалгоритм Хаффмана - C++
есть алгоритм n – количество символов исходного алфавита P – массив вероятностей, упорядоченных по убыванию C – матрица...

Кодирование Хаффмана - C++
Есть дерево Хаффана, с помощью функции, приведенной ниже прохожусь по дереву и &quot;выписываю&quot; 0 и 1, получившиеся коды символов записываю в...

2
Antikl
с++
258 / 254 / 71
Регистрация: 15.07.2015
Сообщений: 1,378
Завершенные тесты: 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
1011 / 751 / 175
Регистрация: 28.07.2012
Сообщений: 2,089
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
Привет! Вот еще темы с ответами:

Алгоритм Хаффмана - C++
Доброго времени суток, пишу сюда, так как отчаялся найти ошибку сам. Собственно проблема состоит в непонимании где я допустил ошибку....

Архиватор Хаффмана c++ - C++
Пишу архиватор на c++ методом Хаффмана. Не могу найти как считывать байты из файла в c++.

Алгоритм Хаффмана - C++
Возможно и наболевшая тема на форуме, но всё же есть реализация алгоритма Хаффмана. Допустим, у меня в файле есть следующая строка: ...

Алгоритм Хаффмана - C++
Ребят, подскажите как реализовать кодирование по алгоритму Хаффмана.. Может есть какие то идеи или исходники (желательно с пояснением)? ...


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

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

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