Cod sursa(job #640117)

Utilizator claudiumihailClaudiu Mihail claudiumihail Data 24 noiembrie 2011 20:06:28
Problema Coduri Huffman Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.21 kb
#include <fstream>
#include <iostream>
#include <cstdlib>

using namespace std;

typedef unsigned short uint16;
typedef unsigned long long uint64;
typedef unsigned long uint32;

#define MAXN 1000100
#define LEFT 0
#define RIGHT 1

#define INF 1LL * 1000000000 * 1000000000

struct Node
{
	uint64 val;
	uint32 child[2];
};

template<typename T>
class CQueue
{
public:
	CQueue(const size_t cap) :
		current(0),
		capacity(cap),
		curSize(0)
	{
		Q = (T*)malloc((cap+1)*sizeof(T));
	}
	
	T front() const
	{
		return Q[current];
	}
	
	void push(const T& elem)
	{
		const size_t pos = (current+curSize) % capacity;
		curSize++;
		Q[pos] = elem;
	}
	
	void pop()
	{
		if (curSize != 0)
		{
			curSize--;
			current++;
			current %= capacity;
		}
	}
	
	bool empty() const
	{
		return (curSize == 0);
	}
	
	size_t size()
	{
		return curSize;
	}
	
	void clear()
	{
		current = 0;
		curSize = 0;
	}
	
	~CQueue()
	{
		free(Q);
	}

private:
	T* Q;
	size_t current;
	size_t capacity;
	size_t curSize;
};

Node huffmanTree[2*MAXN+1];

uint32 BuildHuffManTree(Node huffmanTree[], const uint32 n, uint64& sum)
{
	long st = 1, cur = n+1, last=n;

	sum = 0;
	
	while (n-st+1 + last-cur+1 > 1)
	{	
		/*huffmanTree[cur].val = huffmanTree[index[0]].val + huffmanTree[index[1]].val;
		huffmanTree[cur].child[0] = index[0];
		huffmanTree[cur].child[1] = index[1];*/
		
		for (uint32 i=0; i<2; ++i)
		{
			if (n-st+1>0 && last-cur+1>0)
			{
				if (huffmanTree[st].val <= huffmanTree[cur].val)
				{
					huffmanTree[last+1].val += huffmanTree[st].val;
					huffmanTree[last+1].child[i] = st;
					st++;
				}
				else
				{
					huffmanTree[last+1].val += huffmanTree[cur].val;
					huffmanTree[last+1].child[i] = cur;
					cur++;
				}
			}
			else if (n-st+1>0)
			{
				huffmanTree[last+1].val += huffmanTree[st].val;
				huffmanTree[last+1].child[i] = st;
				st++;
			}
			else if (last-cur+1>0)
			{
				huffmanTree[last+1].val += huffmanTree[cur].val;
				huffmanTree[last+1].child[i] = cur;
				cur++;
			}
			
		}
		
		last++;
		sum += huffmanTree[last].val;
	}
	
	return last;
}

uint32 lg[MAXN];
uint64 values[MAXN];

void GetHuffmanCodes(const uint32 index, const uint16 niv, const uint64 val)
{
	if (huffmanTree[index].child[0])
	{
		GetHuffmanCodes(huffmanTree[index].child[0], niv+1, val<<1);
		GetHuffmanCodes(huffmanTree[index].child[1], niv+1, (val<<1)+1);
	}
	else
	{
		//cout << "Index = " << index-1 << endl;
		lg[index-1] = niv;
		values[index-1] = val;
		//fout << niv << " " << val << "\n";
	}
}

int main()
{
	uint32 n;
	uint64 sum;
	fstream fin("huffman.in", fstream::in);
	fstream fout("huffman.out", fstream::out);
	
	fin >> n;
	//cout << n << endl;
	
	for (uint32 i=1; i<=n; ++i)
	{
		uint32 x;
		fin >> x;
		huffmanTree[i].val = x; 
	}
	
	/*for (int i=0; i<n; ++i)
	{
		cout << huffmanTree[i].val << " ";
	}*/
	
	//cout << endl;
	
	const uint32 rootIndex = BuildHuffManTree(huffmanTree, n+1, sum);
	
	 cout << sum << "\n";
	//GetHuffmanCodes(rootIndex, 0, 0);
	
	for (uint32 i=0; i<n; ++i)
	{
		fout << lg[i] << " " << values[i] << "\n";
	}
	
	fin.close();
	fout.close();
	return 0;
}