unHUff.pas 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. Uses Buffered;
  2. Type
  3. PTree = ^TTree;
  4. TTree = record
  5. info : byte;
  6. ti : longint;
  7. Left : PTree;
  8. Right: PTree;
  9. end;
  10. ps = ^el;
  11. el = record
  12. data : PTree;
  13. prev : ps;
  14. end;
  15. CONST
  16. fname : string[13] = 'input.txt';
  17. fout : string[13] = 'input.huf';
  18. VAR
  19. counts : array [0..255] of longint;
  20. INP,OUT : FILE;
  21. Nums : ps;
  22. THead : PTree;
  23. {-----}
  24. GNum : byte;
  25. done : boolean;
  26. Size,Csize,Go : longint;
  27. LastLen : byte;
  28. {---------------------------------}
  29. Procedure DelBranch(br:PTree);
  30. begin
  31. if br^.left <> nil then DelBranch(br^.left);
  32. if br^.right <> nil then DelBranch(br^.right);
  33. Dispose(br);
  34. end;{DelBranch}
  35. {---------------------------------}
  36. Procedure AddItem(var HEAD:ps; VAL : PTree);
  37. var
  38. c,NEWs : ps;
  39. Begin
  40. c := HEAD;
  41. New(News);
  42. News^.data := VAL;
  43. News^.prev := nil;
  44. if c=nil then
  45. begin
  46. HEAD := NEWs;
  47. exit
  48. end;
  49. if val^.ti <= C^.DATA^.ti then
  50. begin
  51. News^.prev:=C;
  52. HEAD:=News;
  53. exit
  54. end;
  55. while (c^.prev <> nil) and
  56. (not ((val^.ti>C^.data^.ti) and
  57. (val^.ti<=C^.prev^.data^.ti))) do c:=c^.prev;
  58. News^.prev := c^.prev;
  59. C^.prev := News;
  60. end;{AddItem}
  61. {---------------------------------}
  62. Procedure RemoveItem(var HEAD:ps; VAL : PTree);
  63. var
  64. c,cur : ps;
  65. Begin
  66. c := HEAD;
  67. if c=nil then exit;
  68. if c^.data = val then
  69. begin
  70. HEAD:=C^.prev;
  71. Dispose(C);
  72. exit
  73. end;
  74. while (c^.prev <> nil) and (C^.prev^.data <> val) do c:=c^.prev;
  75. if c^.prev^.data <> val then exit;
  76. cur := c^.prev;
  77. C^.prev := cur^.prev;
  78. Dispose(cur);
  79. end;{RemoveItem}
  80. {---------------------------------}
  81. Function GetBit(var F:File):boolean;
  82. var Suxx:byte;
  83. begin
  84. if GNum = 0 then
  85. begin
  86. GNum := 8;
  87. done:=FReadBuf(F,Suxx);
  88. inc(CSize);
  89. go:=Suxx;
  90. if not done then
  91. begin
  92. RBLast:=true;
  93. FReadBuf(F,Suxx);
  94. WBLast:=true;
  95. FWriteBuf(OUT,0);
  96. close(INP);
  97. Close(OUT);
  98. Halt(0);
  99. end;
  100. if csize=Size-1 then begin done:=FReadBuf(F,Gnum) end;
  101. end;
  102. Dec(GNum);
  103. GetBit := (GO and 128) = 128;
  104. Go := GO shl 1;
  105. end;{GetBit}
  106. {----------------------------}
  107. Procedure DeleteAll(var HEAD:ps);
  108. var
  109. c:ps;
  110. begin
  111. while HEAD <> nil do
  112. begin
  113. c:=HEAD^.prev;
  114. Dispose(HEAD);
  115. HEAD := C;
  116. end;
  117. end;{DeleteAll}
  118. {---------------------------------}
  119. Procedure CreateTree;
  120. var
  121. i : byte;
  122. News : PTree;
  123. begin
  124. for i := 0 to 255 do
  125. if counts[i] <> 0 then
  126. begin
  127. New(News);
  128. News^.info:=i;
  129. News^.ti:=counts[i];
  130. News^.Left:=nil;News^.Right:=nil;
  131. AddItem(Nums,News);
  132. end;
  133. while NUMS^.prev <> nil do
  134. begin
  135. New(News);
  136. News^.ti := NUMS^.data^.ti+NUMS^.prev^.data^.ti;
  137. News^.left := Nums^.data;
  138. News^.right := Nums^.prev^.data;
  139. RemoveItem(NUMS,NUMS^.data);
  140. RemoveItem(NUMS,NUMS^.data);
  141. AddItem(NUMS,News);
  142. end;
  143. THead := News;
  144. RemoveItem(NUMS,News);
  145. end;{CreateTree}
  146. {---------------------------------}
  147. Procedure GetTimes(var F:file);
  148. begin BlockRead(F,counts,256*4) end;{GetTimes}
  149. {---------------------------------}
  150. VAR
  151. CURCODE : longint;
  152. curlen : byte;
  153. CUR : byte;
  154. i : byte;
  155. Ctr : Ptree;
  156. BEGIN
  157. if (ParamCount<1) then
  158. begin
  159. WriteLn('Usage: unHUF.exe <FILENAME.EXT> [OUTNAME.ext]');
  160. Halt(10);
  161. end;
  162. Fname := ParamStr(1);
  163. for size := 1 to Length(Fname) do
  164. fname[size] := UpCase(fname[size]);
  165. if Paramcount = 2 then fout := ParamStr(2)
  166. else fout := Copy(Fname,1,pos('.',Fname)) + 'TXT';
  167. Assign(INP,Fname);
  168. Reset(INP,1);
  169. Assign(OUT,Fout);
  170. Rewrite(OUT,1);
  171. Size:=FileSize(INP)-256*4;
  172. GetTimes(INP);
  173. CreateTree;
  174. Ctr := THead;
  175. RBFirst:=true;
  176. WBFirst:=true;
  177. RBLast:=false;
  178. WBLast:=false;
  179. while true do
  180. begin
  181. while CTR^.left <> nil do
  182. begin
  183. if GetBit(INP) then
  184. CTR:=CTR^.left
  185. else
  186. CTR:=CTR^.right;
  187. end;
  188. Write(#13'Complete: ',round((csize/size)*100),'%');
  189. FWriteBuf(OUT,CTR^.INFO);
  190. CTR:=THead;
  191. end;
  192. END.