Pagini recente » Cod sursa (job #2485932) | Cod sursa (job #934134) | Cod sursa (job #195069) | Cod sursa (job #2949627) | Cod sursa (job #2612049)
#include <fstream>
#include <queue>
#include <iostream>
#include <vector>
#include <cctype>
using namespace std;
class InParser {
private:
static const int buffSZ = (1 << 15);
ifstream File;
int buffPos;
char buff[buffSZ];
void _advance() {
if (++buffPos == buffSZ) {
File.read(buff, buffSZ);
buffPos = 0;
}
}
public:
InParser(const char *FileName) {
buffPos = buffSZ - 1;
File.open(FileName);
}
InParser& operator >>(int &no) {
while (!isdigit(buff[buffPos]))
_advance();
no = 0;
while (isdigit(buff[buffPos])) {
no = no * 10 + buff[buffPos] - '0';
_advance();
}
return *this;
}
};
class OutParser {
private:
static const int buffSZ = (1 << 15);
ofstream File;
char buff[buffSZ];
int buffPos;
vector <int> digits;
void _advance() {
if (++buffPos == buffSZ) {
File.write(buff, buffSZ);
buffPos = 0;
}
}
void printChar(char no) {
buff[buffPos] = no;
_advance();
}
public:
OutParser(const char *FileName) {
File.open(FileName);
digits.resize(11);
buffPos = 0;
}
~OutParser() {
File.write(buff, buffPos);
buffPos = 0;
}
OutParser& operator <<(char ch) {
printChar(ch);
return *this;
}
OutParser& operator <<(int no) {
int idx = 0;
if (no == 0)
digits[++idx] = 0;
while (no) {
digits[++idx] = no % 10;
no /= 10;
}
for (; idx; --idx)
printChar(digits[idx] + '0');
return *this;
}
OutParser& operator <<(long long no) {
int idx = 0;
if (no == 0)
digits[++idx] = 0;
while (no) {
digits[++idx] = no % 10;
no /= 10;
}
for (; idx; --idx)
printChar(digits[idx] + '0');
return *this;
}
};
InParser fin("huffman.in");
OutParser fout("huffman.out");
class HuffmanCode {
private:
static vector <int> defaultVector() {
vector <int> a;
return a;
}
struct HeapKey {
int freq, idx;
bool operator < (const HeapKey &other) const {
if (freq == other.freq)
return idx > other.idx;
return freq > other.freq;
}
};
struct HuffmanCodeNode {
int left, right; // left and right children of a node; -1 == NULL
};
priority_queue < HeapKey, vector < HeapKey > > Heap; // minHeap freq + idx
vector <HuffmanCodeNode> sons; // vertices
vector <int> f; // frequencies
vector <long long> base_10Codes;
vector <int> base_2CodeLengths;
int root; // the root is sons.size() - 1 i.e. the last vertex added to the collection
void buildHuffmanCode();
void DFS(int node);
public:
HuffmanCode(const vector <int> &); // initialize with the frequencies of characters in the file
void computeCodes();
long long CodedLength();
void printBase10Codes();
};
HuffmanCode::HuffmanCode(const vector <int> &frequencies = defaultVector()) {
f = frequencies;
for (int idx = 0; idx < (int)f.size(); ++idx)
Heap.push({ f[idx], idx });
sons.resize(f.size(), {-1, -1});
//sons.reserve(2 * f.size() - 1);
buildHuffmanCode();
}
void HuffmanCode::buildHuffmanCode() {
while (Heap.size() > 1) {
int f1 = Heap.top().freq;
int idx1 = Heap.top().idx;
Heap.pop();
int f2 = Heap.top().freq;
int idx2 = Heap.top().idx;
Heap.pop();
sons.push_back({idx1, idx2});
Heap.push({ f1 + f2, (int)sons.size() - 1 });
}
root = (int)sons.size() - 1;
base_10Codes.resize(sons.size(), 0);
base_2CodeLengths.resize(sons.size(), 0);
}
void HuffmanCode::DFS(int node) {
int left = sons[node].left;
int right = sons[node].right;
if (left == -1) // is enough to check for the left son since the tree is full
return;
base_10Codes[left] = 2 * base_10Codes[node];
base_10Codes[right] = 2 * base_10Codes[node] + 1;
base_2CodeLengths[left] = 1 + base_2CodeLengths[node];
base_2CodeLengths[right] = 1 + base_2CodeLengths[node];
DFS(left);
DFS(right);
}
void HuffmanCode::computeCodes() {
DFS(root);
}
long long HuffmanCode::CodedLength() {
long long codedlength = 0;
for (int idx = 0; idx < (int)f.size(); ++idx)
codedlength += 1LL * f[idx] * base_2CodeLengths[idx];
return codedlength;
}
void HuffmanCode::printBase10Codes() {
for (int idx = 0; idx < (int)f.size(); ++idx)
fout << base_2CodeLengths[idx] << ' ' << base_10Codes[idx] << '\n';
}
HuffmanCode hc;
void readData() {
int n;
fin >> n;
vector <int> arr(n);
for (int &itm : arr)
fin >> itm;
hc = arr;
}
int main() {
readData();
hc.computeCodes();
fout << hc.CodedLength() << '\n';
hc.printBase10Codes();
}