For each level, starting at the deepest level of the tree and then moving upwards, leaf nodes must start as far left as possible. An alternative way of stating this constraint is that if any tree node has children then all tree nodes to the left of it with the same path length must also have children.
These 'alternatives' are not equivalent. The latter alternative gives the common canonical code where the longest code is all zeros. The former gives an opposite code where the longest code is all ones. Microsoft uses the former alternative.
112{
118 int leaves_left;
119 int nleaves;
120 int pathlength;
121 unsigned short cur_code;
122 short codes_too_long = 0;
125
130 }
132 for (leaves_left = 0; leaves_left <
nelem; leaves_left++) {
133#ifdef DEBUG_HUFFMAN
134 fprintf(
stderr,
"%3d: %3d '%c'\n", leaves_left, leaves[leaves_left].freq,
135 leaves[leaves_left].sym);
136#endif
137 if (!leaves[leaves_left].freq) break;
138 }
139 nleaves = leaves_left;
140
141 if (nleaves >= 2) {
143 do {
144 if (codes_too_long) {
145 for (leaves_left = 0; leaves_left <
nelem; leaves_left++) {
146 if (!leaves[leaves_left].freq) break;
147 if (leaves[leaves_left].freq != 1) {
148 leaves[leaves_left].
freq >>= 1;
149 codes_too_long = 0;
150 }
151 }
153 }
154
155 cur_leaf = leaves;
156 next_inode = cur_inode = inodes;
157
158 do {
160 if (leaves_left &&
161 ((cur_inode == next_inode) ||
162 (cur_leaf->
freq <= cur_inode->
freq))) {
164 leaves_left--;
165 }
166 else if (cur_inode != next_inode) {
168 }
169
170 if (leaves_left &&
171 ((cur_inode == next_inode) ||
172 (cur_leaf->
freq <= cur_inode->
freq))) {
174 leaves_left--;
175 }
176 else if (cur_inode != next_inode) {
178 }
179
180#ifdef DEBUG_HUFFMAN
182#endif
184 next_inode->
freq =
f1->freq +
f2->freq;
185 next_inode->
sym = -1;
189 f1->parent = next_inode;
190 f2->parent = next_inode;
191 if (
f1->pathlength >
f2->pathlength)
193 else
195 if (next_inode->
pathlength > max_code_length) {
196 codes_too_long = 1;
197 break;
198 }
199 next_inode++;
200 }
201 }
203 }
204 while (codes_too_long);
205
206#ifdef DEBUG_HUFFMAN
207 cur_inode = inodes;
208 while (cur_inode < next_inode) {
210 cur_inode - inodes,
211 (cur_inode->
left->sym!=-1)?(((
struct h_elem *)cur_inode->
left)-leaves):(cur_inode->
left-inodes),
212 (cur_inode->
left->sym!=-1)?
'l':
'i',
214 (cur_inode->
right->sym!=-1)?
'l':
'i',
216 );
217 cur_inode++;
218 }
219#endif
220
221
222 cur_inode = next_inode - 1;
223 pathlength = 0;
225 do {
226
227 if (cur_inode->
sym == -1) {
228
229 cur_inode = cur_inode->
left;
231 pathlength++;
232 }
233 else {
234
236#if 0
237 if (cur_inode->
right) {
238
239 cur_inode = cur_inode->
right;
241 pathlength++;
242 }
243 else
244#endif
245 {
246
247
248
249 do {
250 cur_inode = cur_inode->
parent;
251 pathlength--;
252 }
253 while (cur_inode && (cur_inode->
pathlength != -1));
254 if (cur_inode) {
255
257 cur_inode = cur_inode->
right;
259 pathlength++;
260
261 }
262 }
263 }
264 }
265 while (cur_inode);
266
267#ifdef DEBUG_HUFFMAN
268 cur_inode = inodes;
269 while (cur_inode < next_inode) {
270 fprintf(
stderr,
"%d l: %3d%c r: %3d%c freq: %8d pathlength %4d\n",
271 cur_inode - inodes,
272 (cur_inode->
left->sym!=-1)?(((
struct h_elem *)cur_inode->
left)-leaves):(cur_inode->
left-inodes),
273 (cur_inode->
left->sym!=-1)?
'l':
'i',
275 (cur_inode->
right->sym!=-1)?
'l':
'i',
278 );
279 cur_inode++;
280 }
281#endif
283
284
286
302#if 0
304 cur_code = 0;
305 for (
i = 0;
i < nleaves;
i++) {
306 while (leaves[
i].pathlength < pathlength) {
308 cur_code >>= 1;
309 pathlength--;
310 }
311 leaves[
i].
code = cur_code;
312 cur_code++;
313 }
314#else
316 assert(leaves[0].pathlength <= 16);
317
318
319 cur_code = 0;
320 for (
i = nleaves - 1;
i >= 0;
i--) {
321 while (leaves[
i].pathlength > pathlength) {
322 cur_code <<= 1;
323 pathlength++;
324 }
325 leaves[
i].
code = cur_code;
326 cur_code++;
327 }
328#endif
329
330#ifdef DEBUG_HUFFMAN
331 for (
i = 0;
i < nleaves;
i++) {
334
335 cur_code = leaves[
i].
code;
337 for (
j = leaves[
i].pathlength-1;
j >= 0;
j--) {
338 if (cur_code & 1)
code[
j] =
'1';
340 cur_code >>= 1;
341 }
344 }
345#endif
346 }
347 else if (nleaves == 1) {
348
349
350 nleaves = 2;
351 leaves[0].pathlength = leaves[1].pathlength = 1;
352 if (leaves[1].sym > leaves[0].sym) {
353 leaves[1].code = 1;
354 leaves[0].code = 0;
355 }
356 else {
357 leaves[0].code = 1;
358 leaves[1].code = 0;
359 }
360 }
361
363 for (
i = 0;
i < nleaves;
i++) {
364 tree[leaves[
i].sym].codelength = leaves[
i].pathlength;
365 tree[leaves[
i].sym].code = leaves[
i].code;
366 }
367
369}
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
static int cmp_pathlengths(const void *in_a, const void *in_b)
static int cmp_leaves(const void *in_a, const void *in_b)
void __cdecl qsort(_Inout_updates_bytes_(_NumOfElements *_SizeOfElements) void *_Base, _In_ size_t _NumOfElements, _In_ size_t _SizeOfElements, _In_ int(__cdecl *_PtFuncCompare)(const void *, const void *))