Kompresja LZW (+pytanie odnośnie kompresji Huffmana)

0

Witam, jakiś czas programuję w języku C++, jednak moja znajomość języka obejmuje głównie podstawy. Niezbyt dobrze czuję się w programowaniu obiektowym, a niestety muszę napisać kompresję danych we właśnie takiej strukturze.
Napisałem program w oparciu o schemat blokowy metody LZW. Proszę nie wypominać braku enkapsulacji, chwilowo wszystkie elementy klasy udostępniłem publicznie, żeby łatwiej wyłapać błędy. Zastanawiam się, czy powinienem także jakoś wyeksportowac słownik? Wypisywanie tablicy zamienię na wpis do pliku, jednak dla ułatwienia debugowania wypisuję chwilowo na ekran.

Z początku metoda kons() była konstruktorem, zmieniłem ją na zwykłą metodę, ponieważ nie byłem pewien poprawności tak rozbudowanego konstruktora.
Problem pojawia się przy jej wywołaniu, nie potrafię zlokalizować źródła.

Proszę o pomoc w zdebugowaniu tego programu i o ew. wskazówki jak mogę kod zoptymalizować lub poprawić. Domyślam, że błędów może wciąż być sporo, ale bez rozwiązania wywalania programu na samym początku, nie mogę ich zlokalizować.
Z góry dziękuję za pomoc.

 // Kompresja LZW.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <conio.h>
#include <fstream>
#include <stdlib.h>
#include <string>

using namespace std;
const int wielkosc=10;
class lzw
{
	public:
	char slownik[wielkosc][wielkosc];
	fstream plik;
	char c[1];
	char s[wielkosc];
	int tab[wielkosc];

	void kons()
	{
		for(int i=0;i<wielkosc;i++)
		{
			s[i]=NULL;
			strcpy(slownik[i],NULL);
			tab[i]=0;
		}
		strcpy(c,NULL);
		int i=0;
		plik.open("C:\pliczek.txt",std::ios::in);
		if(plik.good()==true)
		{
			while(plik.eof()!=1)
			{
				plik>>c[0];
				i=0;
				while(1)
				{
					if(slownik[i][0]==c[0])
						break;
					else
					{
						i++;
						if(slownik[i][0]==NULL)
						{
							slownik[i][0]=c[0];
							break;
						}
					}
				}

			}
		}
		plik.close();
	}

	void wczytuj()
	{
		int i=0;
		int j=0;
		char sprawdz[wielkosc]={0};
		fstream plik;
		plik.open("C:\pliczek.txt",std::ios::in);
		if(plik.good()==true)
		{
			while(plik.eof()!=1)
			{
				plik>>c;
				i=0;
				strcpy(sprawdz,s);
				strcat(sprawdz,c);
				while(1)
				{
					if(slownik[i]==sprawdz)
					{
						strcat(s,c);
						break;
					}
					else if(slownik[i]!=sprawdz)
					{
						i++;
						if(slownik[i]==NULL)
						{
							tab[j]=i;
							j++;
							strcpy(slownik[i],sprawdz);
							strcpy(s,c);
							break;
						}
					}
				}

			}
		}
	}

	void wypisz()
	{
		for(int i=0;i<wielkosc;i++)
			cout<<tab[i];
	}
};
int _tmain(int argc, _TCHAR* argv[])
{
	lzw *ob=new lzw();
	ob->kons();
	ob->wczytuj();
	ob->wypisz();
	getch();
	return 0;
} 

Przy okazji także zapytam o kompresję Huffmana. Napisałem ją proceduralnie i wydaje mi się, że poprawnie koduje dane, jednak wielkość pliku wyjściowego jest znacznie większa niż wejściowego. Drzewo buduję wg. schematu z wikipedii - w każdy korzeniu poddrzewa jest tylko jeden prawy syn i reszta drzewa w lewym synu. Obawiam się, że przez to kod ostatnich elementów jest zbyt długi. Czy to może być problemem? Jak mogę w prosty sposób naprawić ten program? (Jeśli to krótkie wyjaśnienie jest niewystarczające, to mogę wrzucić kod, jednak wolę najpierw rozwiązać problem z kompresją LZW).

0

Drzewo buduję wg. schematu z wikipedii - w każdy korzeniu poddrzewa jest tylko jeden prawy syn i reszta drzewa w lewym synu. Obawiam się, że przez to kod ostatnich elementów jest zbyt długi.

Gdzie ty taki schemat widzisz na wiki? Weźmy na przykład: http://upload.wikimedia.org/wikipedia/commons/8/82/Tobeornot.png Widać, że sporo liści jest na tym samym poziomie.

LZW się nie zajmowałem.

0

http://pl.wikipedia.org/w/index.php?title=Plik:Huffman_coding-example.svg&filetimestamp=20100328101810
Niestety wziąłem się za programowanie kodu Huffmana na podstawie tego drzewa. Nawet jeśli przekształcę drzewo na właściwie, w jaki sposób mogę przejść je zapisując kody poszczególnych znaków? Trzy główne przejścia rekurencyjne idą tylko po liściach i nie wiem jak mógłbym otrzymać kod każdego liścia.

0

Identycznie jak na obrazku. Przechodząc do jednego syna dodajesz zero do aktualnego prefiksu, a przechodząc do drugiego dodajesz jedynkę.

1 użytkowników online, w tym zalogowanych: 0, gości: 1