Program Compress; Const MaxCharType=7000; Type TreeLink=^TreeNode; TreeNode=Record CharName:Char; Left:TreeLink; Right:TreeLink; Freqency:Word; end; CharLink=^CharNode; CharNode=Record CharName:Char; Next:CharLink; end; CharInfor=Record CharName:Char; CodeLink:CharLink; end; Arr=array [1..MaxCharType] of TreeLink; CharArr=array [1..MaxCharType] of CharInfor; Var WorkArr:Arr; TCode:CharArr; FileHead,Original:string; p,q:TreeLink; code,count,TotalCharType,TempVar:word; infile:text; outfile,testfile:file; procedure insert (Var WorkArr:Arr;c:char;Var len:word); var j:word; found:boolean; begin found:=false; for j:=1 to len do if (WorkArr[j]^.CharName=c) then begin inc (WorkArr[j]^.Freqency); found:=true; exit; end; if not found then begin New (WorkArr[len+1]); With WorkArr[len+1]^ do begin CharName:=c; Freqency:=1; Left:=Nil; Right:=Nil; end; inc(len); end; end; procedure sort(Var WorkArr:Arr;i,j:word); var x,y,t,z:word; u:TreeLink; begin for x:=i to j-1 do begin t:=WorkArr[x]^.Freqency; z:=x; for y:=x+1 to j do begin if WorkArr[y]^.FreqencyNil) then begin if (u^.CharName<>#0) then begin TCode[TotalCharType+1].CharName:=u^.CharName; temp:=1; New (TCode[TotalCharType+1].CodeLink); v:=TCode[TotalCharType+1].CodeLink; while temp<=length(t) do begin new (TChar); TChar^.CharName:=t[temp]; TChar^.Next:=Nil; v^.Next:=TChar; v:=v^.Next; inc(temp); end; inc(TotalCharType); end else begin preorder(u^.Left,t+'0',TotalCharType); preorder(u^.Right,t+'1',TotalCharType); end; end; end; procedure fileout(Original:string;TotalCharType:word); var k,j,NumWritten:word; v:CharLink; begin for k:=1 to length(Original) do begin for j:=1 to TotalCharType do begin if Tcode[j].CharName=Original[k] then begin v:=TCode[j].CodeLink^.Next; while v<>Nil do begin code:=code+(2 shl (7-count))*(ord(v^.CharName)-48); inc(count); if count>7 then begin count:=1; blockwrite (outfile,code,1,NumWritten); code:=0; end; v:=v^.Next; end; end; end; end; end; procedure init; begin New (WorkArr[1]); if Paramcount<2 then begin writeln; writeln (' Huffman File Convertor V1.0'); writeln ('Usages:Huffman File1 File2 [1|2]'); writeln ('1-To Convert File1 into File2 (Default)'); writeln ('2-To Restore File2 from File1'); writeln; halt(0); end; code:=0; count:=1; TotalCharType:=0; FileHead:='Huffman Tree File'; end; procedure prread(Original:string); var i:word; begin i:=1; Repeat insert (WorkArr,Original[i],TempVar); inc(i); Until i>length(Original); end; procedure parse; var u:TreeLink; len:word; begin len:=TempVar; sort (WorkArr,1,len); while len>1 do begin New (u); u^.Freqency:=WorkArr[1]^.Freqency+WorkArr[2]^.Freqency; u^.CharName:=#0; u^.Left:=WorkArr[1]; u^.Right:=WorkArr[2]; WorkArr[1]:=u; WorkArr[2]:=WorkArr[len]; dec(len); sort (WorkArr,1,len); end; end; procedure restorefile; var i:word; begin assign (outfile,Paramstr(1)); reset (outfile,1); assign (infile,Paramstr(2)); rewrite (infile); count:=0; BlockRead(outfile,Original,sizeOf(FileHead),TempVar); if (Original<>FileHead) then begin writeln ('File Head Error!'); halt(0); end; BlockRead(outfile,TotalCharType,SizeOf(TotalCharType),TempVar); for i:=1 to TotalCharType do begin New (WorkArr[i]); BlockRead(outfile,WorkArr[i]^.CharName,SizeOf(WorkArr[i]^.CharName),TempVar); BlockRead(outfile,WorkArr[i]^.Freqency,SizeOf(WorkArr[i]^.Freqency),TempVar); WorkArr[i]^.Left:=Nil; WorkArr[i]^.Right:=Nil; end; TempVar:=TotalCharType; parse; preorder(WorkArr[1],'0',TotalCharType); New (q); q^.Left:=WorkArr[1]; q^.Right:=WorkArr[1]; p:=q; BlockRead(outfile,code,1,TotalCharType); repeat inc(count); if (count>7) then begin count:=1; BlockRead(outfile,code,1,TempVar); end; if code>=2 shl (7-count) then begin p:=p^.Right; code:=code-(2 shl (7-count)); end else p:=p^.Left; if p^.CharName<>#0 then begin write (infile,p^.CharName); p:=q; end; until (TempVar=0); close(outfile); close(infile); halt(0); end; procedure compressfile; var i,j:word; begin assign (outfile,Paramstr(2)); rewrite (outfile,1); assign (infile,Paramstr(1)); reset (infile); repeat readln (infile,Original); Original:=Original+#10+#13; prread(Original); until Eof(infile); BlockWrite (outfile,FileHead,SizeOf(FileHead),j); BlockWrite (outfile,TempVar,SizeOf(TempVar),j); for i:=1 to TempVar do begin blockwrite (outfile,WorkArr[i]^.CharName,SizeOf(WorkArr[i]^.CharName),j); blockwrite (outfile,WorkArr[i]^.Freqency,SizeOf(WorkArr[i]^.Freqency),j); end; parse; close(infile); assign (infile,Paramstr(1)); reset (infile); preorder(WorkArr[1],'0',TotalCharType); Repeat readln(infile,Original); Original:=Original+#10+#13; fileout(Original,TotalCharType); Until Eof(infile); blockwrite (outfile,code,1,TempVar); close(outfile); close(infile); end; Begin init; if Paramstr(3)='2' then restorefile else compressfile; End.