Смекни!
smekni.com

Компрессия информации и упорядочение дерева по алгоритму Виттера (стр. 4 из 4)

if DCounter=0 then

DCounter: =7 else

dec(DCounter);

DByte: =((DByte shl 1) or (byte(bit) and 1));

if DCounter=0 then

begin

AddSymbol(DecodeTree,chr(DByte));

CheckWiegth(DecodeTree);

Enumerate(DecodeTree);

Huffman(DecodeTree);

Vitter(DecodeTree);

DrawTree(Form1. Panel2,DecodeTree,Form1. Panel2. ClientWidth,500);

MakeDeCodeTable(DecodeTree);

AddCharToDMess(chr(DByte));

DString: ='';

DB: =false;

end;

end else

if DecodeTree=nil then

begin

DB: =true;

Decode(BIT);

end else

begin

DString: =DString + Bit;

for c: =#0 to #255 do

begin

if DecodeTable [c] =DString then

begin

if c=#0 then

begin

DB: =true;

DCounter: =0;

end else

begin

AddSymbol(DecodeTree,c);

CheckWiegth(DecodeTree);

Enumerate(DecodeTree);

Huffman(DecodeTree);

Vitter(DecodeTree);

DrawTree(Form1. Panel2,DecodeTree,Form1. Panel2. ClientWidth,500);

MakeDeCodeTable(DecodeTree);

DString: ='';

AddCharToDMess(c);

DB: =false;

break;

end;

end;

end;

end;

end;

procedure MakeCodeTable(Top: PTree);

procedure CT(P: PTree; code: string);

begin

if P<>nil then

begin

if (P. Wiegth>=0) and (P. IsLeaf) then

begin

codetable [P. Symbol] : =code;

end;

if not P. IsLeaf then

begin

CT(P. Left,code+'0');

CT(P. Right,code+'1');

end;

end;

end;

begin

CT(Top,'');

end;

procedure ShowCT;

var

C: Char;

begin

Form1. CodeTableMemo. Clear;

For c: =#0 to #255 do

begin

if CodeTable [c] <>'' then

begin

Form1. CodeTableMemo. Lines. Append(c+' - '+CodeTable [c]);

end;

end;

end;

procedure AddCharToMess(C: Char);

var

S: String;

begin

With Form1. MessageMemo do

begin

S: =Text;

Clear;

Text: =S+C;

end;

end;

procedure AddCoded(c: char);

var

s: string;

begin

S: =Form1. CodedMsg. Lines. Text;

Form1. CodedMsg. Clear;

Form1. CodedMsg. Lines. Text: =S+' '+CodeTable [c];

end;

procedure AddASC(c: char);

var

i: integer;

s: string;

b: byte;

begin

s: ='';

b: =byte(c);

for i: =1 to 8 do

begin

s: =chr((b and 1) +$30) +s;

b: =(b shr 1);

end;

S: =Form1. CodedMsg. Lines. Text+' '+s;

Form1. CodedMsg. Clear;

Form1. CodedMsg. Lines. Text: =S;

end;

procedure TForm1. InCharKeyPress(Sender: TObject; var Key: Char);

var

B: Boolean;

begin

B: =AddSymbol(Tree,Key);

CheckWiegth(Tree);

Enumerate(Tree);

Huffman(Tree);

DrawTree(Panel1,Tree,Panel1. ClientWidth,500);

Application. MessageBox('stop','stop',MB_OK);

Vitter(Tree);

DrawTree(Panel1,Tree,Panel1. ClientWidth,500);

if B then

begin

AddCoded(#0);

AddASC(key);

end else

begin

AddCoded(key);

end;

MakeCodeTable(Tree);

AddCharToMess(Key);

ShowCT;

InChar. Clear;

end;

procedure TForm1. Button1Click(Sender: TObject);

var

s: string;

c: char;

begin

s: =CodedMsg. Text;

if(s<>'') then

begin

while s [1] =' ' do Delete(s,1,1);

while ((s<>'') and (s [1] <>' ')) do

begin

Decode(s [1]);

Delete(s,1,1);

end;

CodedMsg. Clear;

CodedMsg. Text: =s;

end;

end;

procedure TForm1. FormResize(Sender: TObject);

begin

Panel1. Top: =20;

Panel1. Height: =(ClientHeight div 2) - 20;

Label2. Top: =(ClientHeight div 2);

Panel2. top: =(ClientHeight div 2) +20;

Panel2. Height: =(ClientHeight div 2) - 20;

end;

procedure TForm1. FormPaint(Sender: TObject);

begin

DrawTree(Panel1,Tree,Panel1. ClientWidth,500);

DrawTree(Panel2,DecodeTree,Panel2. ClientWidth,500);

end;

procedure TForm1. Button2Click(Sender: TObject);

var

s: string;

c: char;

begin

s: =CodedMsg. Text;

if(s<>'') then

begin

while s [1] =' ' do Delete(s,1,1);

if ((s<>'') and (s [1] <>' ')) then

begin

Decode(s [1]);

Delete(s,1,1);

end;

CodedMsg. Clear;

CodedMsg. Text: =s;

end;

end;

end.

unit Core;

{$B-}

interface

uses Graphics;

type

PTree = ^TTree;

TTree = record

Left,Right,Up: PTree;

Symbol: char;

Wiegth: integer;

Number: integer;

IsLeaf: boolean;

end;

function NewNode(l,r,u: PTree; s: char; c,n: integer; i: boolean): PTree;

procedure DeleteTree(var P: PTree);

function AddNewSymbolToTree(var Top: PTree; c: char): boolean;

function AddSymbolToTree(var Top: PTree; c: char): boolean;

function AddSymbol(var Top: PTree; c: char): boolean;

function MaxLevel(Top: PTree): integer;

procedure NodesOnLevel(Top: PTree; var qol: integer; l,level: integer);

function GetNodeFromLevel(P: Ptree; level,number: integer; var l,n: integer): PTree;

procedure Enumerate(P: PTree);

function CheckWiegth(P: PTree): integer;

function GetNodeByNumber(P: PTree; number: integer): PTree;

function GetLeafByWiegthMax(P: PTree; wiegth: integer): PTree;

procedure Vitter(P: PTree);

procedure Huffman(P: PTree);

implementation

Uses Math,SysUtils;

{$B-}

function CheckWiegth(P: PTree): integer;

begin

Result: =0;

if P<>nil then

begin

if not P. Isleaf then

begin

Result: =CheckWiegth(P. left) +CheckWiegth(P. right);

P. Wiegth: =Result;

end else Result: =P. Wiegth;

end else

Result: =0;

end;

procedure Huffman(P: PTree);

var

i,j,k: integer;

t,tt: PTree;

tmp: TTree;

begin

k: =1;

t: =GetNodeByNumber(P,k);

while t<>nil do

begin

tt: =GetNodeByNumber(P,k+1);

if tt<>nil then

begin

if tt. Wiegth<t. Wiegth then

begin

move(tt^,tmp,sizeof(tmp));

move(t^,tt^,sizeof(tmp));

move(tmp,t^,sizeof(tmp));

CheckWiegth(P);

Enumerate(P);

k: =1;

end;

end;

inc(k);

T: =GetNodeByNumber(P,k);

end;

end;

procedure Vitter(P: PTree);

var

i,j,k,l: integer;

t,tt,ttt: PTree;

tmp: TTree;

begin

k: =1;

t: =GetNodeByNumber(P,1);

while t<>nil do

begin

if not T. IsLeaf then

begin

tt: =GetLeafByWiegthMax(P,t. wiegth);

if(tt<>nil) then

begin

if(tt. Number>T. Number) then

begin

move(tt^,tmp,sizeof(tmp));

move(t^,tt^,sizeof(tmp));

move(tmp,t^,sizeof(tmp));

CheckWiegth(P);

Enumerate(P);

k: =1;

end;

end;

end;

inc(k);

T: =GetNodeByNumber(P,k);

end;

end;

function GetLeafByWiegthMax(P: PTree; wiegth: integer): PTree;

var

i: integer;

Node: PTree;

begin

Result: =nil;

i: =1;

Node: =GetNodeByNumber(P, i);

while Node<>nil do

begin

if Node. Wiegth > wiegth then exit; // ???????

if Node. IsLeaf and (Node. Wiegth=wiegth) then

begin

Result: =Node;

end;

inc(i);

Node: =GetNodeByNumber(P, i);

end;

end;

function GetNodeByNumber(P: PTree; number: integer): PTree;

begin

if(P<>nil) then

begin

if P. Number=number then result: =P else

begin

Result: =GetNodeByNumber(P. Left,number);

if Result=nil then Result: =GetNodeByNumber(P. Right,number);

end;

end else Result: =nil;

end;

procedure Enumerate(P: PTree);

var

i,j,k,l,n,o,s: integer;

T: PTree;

begin

n: =0;

k: =MaxLevel(P);

for i: =k downto 1 do

begin

o: =1;

s: =1;

l: =1;

T: =GetNodeFromLevel(P, i,l,o,s);

while T<>nil do

begin

inc(n);

T. Number: =n;

inc(l);

o: =1;

s: =1;

T: =GetNodeFromLevel(P, i,l,o,s);

end;

end;

end;

function GetNodeFromLevel(P: PTREE; level,number: integer; var l,n: integer): PTree;

var

T: PTRee;

begin

result: =nil;

if(P<>nil) then

begin

if(l<level) then

begin

inc(l);

T: =GetNodeFromLevel(P. Left,level,number,l,n);

dec(l);

if(T=nil) then

begin

inc(l);

Result: =GetNodeFromLevel(P. Right,level,number,l,n);

dec(l);

end

else Result: =T;

end else

begin

if(l=level) then

begin

if(n=number) then result: =P else

begin

result: =nil;

end;

inc(n);

end else result: =nil;

end;

end else

result: =nil;

end;

procedure NodesOnLevel(Top: PTree; var qol: integer; l,level: integer);

begin

if Top<>nil then

begin

if level=l then

begin

inc(qol);

end else

begin

NodesOnLevel(top. Left,qol,l+1,Level);

NodesOnLevel(top. Right,qol,l+1,Level);

end;

end;

end;

function MaxLevel(Top: PTree): integer;

begin

if(Top=nil) then

begin

Result: =0;

end else

begin

Result: =Max(MaxLevel(Top. Left),MaxLevel(Top. Right)) +1;

end;

end;

function AddSymbol(var Top: PTree; c: char): boolean;

begin

if(not AddSymbolToTree(Top,c)) then

if(not AddNewSymbolToTree(Top,c)) then

result: =false // Error

else

result: =true // Added

else

result: =false; // Updated

end;

function AddSymbolToTree(var Top: PTree; c: char): boolean;

begin

if Top=nil then Result: =False else

begin

if Top. IsLeaf then

begin

if Top. Symbol=c then

begin

inc(Top. Wiegth);

result: =true;

end else

begin

result: =false;

end;

end else

begin

if AddSymbolToTree(Top. left,c) or AddSymbolToTree(Top. right,c) then

begin

inc(Top. Wiegth);

result: =true;

end else

result: =false;

end;

end;

end;

function AddNewSymbolToTree(var Top: PTree; c: char): boolean;

begin

if Top=nil then

begin

Top: =NewNode(nil,nil,nil,#0,1,0,false);

Top. left: =NewNode(nil,nil,Top,#0,0,0,true);

Top. Right: =NewNode(nil,nil,Top,c,1,0,true);

result: =true;

end else

begin

if (Top. Wiegth=0) and (top. Symbol=#0) then

begin

Top. Left: =NewNode(nil,nil,Top,#0,0,0,true);

Top. Right: =NewNode(nil,nil,Top,c,1,0,true);

Top. IsLeaf: =false;

Top. Wiegth: =1;

Result: =true;

end else

begin

if (Top. Left<>nil) and AddNewSymbolToTree(Top. Left,c) then

begin

result: =true;

exit;

end;

if (Top. Right<>nil) and AddNewSymbolToTree(Top. Right,c) then

begin

result: =true;

exit;

end;

result: =false;

end;

end;

end;

procedure DeleteTree(var P: PTree);

begin

if P=nil then exit;

DeleteTree(P. Left);

DeleteTree(P. Right);

Dispose(P);

P: =nil;

end;

function NewNode(l,r,u: ptree; s: char; c,n: integer; i: boolean): PTree;

var

P: PTree;

begin

new(P);

P. Left: =l;

P. Right: =r;

P. Up: =u;

P. Symbol: =s;

P. Wiegth: =c;

P. Number: =n;

P. IsLeaf: =i;

result: =P;

end;

end.