Annotation of researchv10no/libc/gen/huff.c, revision 1.1.1.1

1.1       root        1: /*  This program gets a histogram of elements that consist
                      2: of a pointer to a char[] and a probability or number of occurances
                      3: for each.  The size of the char[] is up to you, you pass back
                      4: a pointer to it (and you make it in the first place in the loading
                      5: routine, called getstuf(**char,*float)  At the end, you will
                      6: be presented with a NODE * pointer to the head of both the
                      7: linked list and the top of the huffman code tree.  The linked
                      8: list is in order of generation, from most likely to least,
                      9: including the internodes as well as terminal nodes.  The tree
                     10: is a tree, naturally...  
                     11: 
                     12:        Written by James Johnston, AT&T Bell Labs, 6/2/87.  
                     13:        Copyrighted code, all rights reserved to AT&T per
                     14:        employment agreement, etc, etc, etc                     */
                     15: 
                     16: #include <stdio.h>
                     17: #include <huff.h>
                     18: 
                     19: static int compar();
                     20: static NODE *mknd(), *loadall(), *putone(), *taketwo();
                     21: double log();
                     22: 
                     23: NODE *
                     24: huff(inrout)
                     25: int ( *inrout)();
                     26: {
                     27:        NODE * active, * result, * tmp;
                     28:        NODE ** tmps, ** arhead;
                     29:        int i, j, k, max;
                     30: 
                     31:        active=(NODE *)0;
                     32:        result=(NODE *)0;
                     33: 
                     34:        active=loadall(inrout);
                     35:        /* loadall returns a pointer to the beginning */
                     36:        tmp=active;
                     37:        max=0;
                     38:        /* count how many */
                     39:        while ( tmp != (NODE *) 0 ) {
                     40:                tmp=tmp->to;
                     41:                max++;
                     42:        }
                     43:        /* load pointer array for sorting */
                     44:        arhead= (NODE **) malloc(max*sizeof(NODE *));
                     45:        if (arhead == (NODE **) 0 ) {
                     46:                fprintf(stderr,"can't malloc sorting array");
                     47:                exit();
                     48:        }
                     49:        tmp = active;
                     50:        tmps=arhead;
                     51:        while ( tmp != (NODE *) 0 ) {
                     52:                *(tmps++)=tmp;
                     53:                tmp = tmp -> to;
                     54:        }
                     55:        qsort(arhead,max,sizeof(NODE *), compar);
                     56:        /* relink list */
                     57: 
                     58:        active= *arhead;
                     59:        active->from=(NODE *) 0;
                     60:        active->to=arhead[1];
                     61:        for ( i=1; i<max-1; i++) {
                     62:                arhead[i]->to=arhead[i+1];
                     63:                arhead[i]->from=arhead[i-1];
                     64:        }
                     65:        arhead[max-1]->to=(NODE *)0;
                     66:        arhead[max-1]->from=arhead[max-2];
                     67:        /* now it's reloaded */
                     68: 
                     69:        free(arhead);
                     70: 
                     71:        /* this takes the first two elements of the list away, and puts
                     72:        a third one in wherever it fits, in order */
                     73:        while  (active->to != (NODE *) 0 ) {
                     74:                tmp=taketwo(&active,&result);
                     75:                active=putone(tmp,active);
                     76:        }
                     77:        /* now we're done, put the one remaining on the result list */
                     78:        result->from=active;
                     79:        active->to=result;
                     80:        active->from= (NODE *) 0;
                     81:        result=active;
                     82:        active=(NODE *) 0;
                     83: 
                     84: 
                     85: 
                     86:        return result;
                     87: }
                     88: 
                     89: static NODE *
                     90: putone(new, active)
                     91: NODE * new, *active;
                     92: {
                     93:        /* this puts tmp into place in the active list, in order of
                     94:        probability.  This relies utterly on the list being sorted already,
                     95:        and failure to do so will cause utter chaos*/
                     96: 
                     97:        NODE * tmp, *after, *tmpp;
                     98: 
                     99:        tmp=active;
                    100: 
                    101:        after = (NODE *) 0;
                    102:        while ( ( tmp != (NODE *)0 ) &&
                    103:            (new->prob > tmp->prob ) ) {
                    104:                after=tmp;
                    105:                tmp=tmp->to;
                    106:        }
                    107:        /* goes until you find an element more probable or you get to the end*/
                    108:        /* now, insert tmp into the list, being careful if it's first */
                    109:        if (after == (NODE *) 0 ) {
                    110:                new->from=(NODE *) 0;
                    111:                new->to=active;
                    112:                if ( active != (NODE *) 0 ) active->from=new;
                    113:                return new;
                    114:                /* put it first */
                    115:        }
                    116:        tmp=after->to;
                    117:        /* tmp is now the one to put after the new one */
                    118:        if ( tmp != (NODE *) 0 ) tmp->from=new;
                    119:        new->to=tmp;
                    120:        /* now set up the before node, in variable after.  sheesh! */
                    121:        after->to=new;
                    122:        new->from=after;
                    123:        return active;
                    124: }
                    125: 
                    126: static NODE *
                    127: taketwo(actp,resp)
                    128: NODE ** actp, ** resp;
                    129: {
                    130:        NODE * active, *tmp, *result, * tmp1;
                    131: 
                    132:        active = *actp;
                    133:        /* temporary active pointer */
                    134:        result = *resp;
                    135:        /* temp result pointer */
                    136:        tmp=mknd();
                    137:        /* make new node */
                    138:        tmp->ldad=active;
                    139:        /* load left father */
                    140:        tmp->rdad=active->to;
                    141:        /* load right father */
                    142:        active->kid=tmp;
                    143:        active->to->kid=tmp;
                    144:        /* load kid node into fathers */
                    145:        tmp->prob=active->prob+active->to->prob;
                    146:        /* sum probabilities of fathers into the kid*/
                    147:        tmp->datump=(char *) 0;
                    148:        /* make sure that there's no character pointer in the kid */
                    149:        *actp=active->to->to;
                    150:        /* set the new head of the active list */
                    151:        if ( *actp != (NODE *) 0 ) (*actp)->from=(NODE *) 0;
                    152:        /* make the from of the new active pointer null unless there's
                    153:                no longer an active pointer due to end of algorithm*/
                    154: 
                    155:        *resp=active->to;
                    156:        /* remember which was second in line */
                    157:        /* and set the new result pointer */
                    158:        active->to=result;
                    159:        if ( result != (NODE *) 0 ) result->from=active;
                    160:        /* put head of active to head of result. */
                    161: 
                    162:        (*resp)->to=active;
                    163:        /* point next on result stack to new entry */
                    164:        active->from=(*resp);
                    165:        (*resp)->from=(NODE *)0;
                    166:        return tmp;
                    167:        /* return the new, unattached, node */
                    168: }
                    169: 
                    170: static NODE *
                    171: mknd()
                    172: {
                    173:        NODE *temp;
                    174:        if ( (temp=(NODE *)malloc(sizeof(NODE) ) ) == NULL )
                    175:        {       
                    176:                fprintf(stderr,"could not make NODE");
                    177:                exit();
                    178:        }
                    179:        return temp;
                    180: }
                    181: static NODE * 
                    182: loadall(inrout)
                    183: int ( *inrout)();
                    184: {
                    185:        float tprob;
                    186:        char * tdp;
                    187:        NODE * tmp, *last,* first, * backp;
                    188:        last = (NODE *)0;
                    189:        while ( ((*inrout)(&tdp,&tprob) != 0) ) {
                    190:                tmp = mknd();
                    191:                first=tmp;
                    192:                /* first keeps track of what will go into the return value,
                    193:                                                                                                        eventually*/
                    194:                tmp->to=last;
                    195:                if (last != ( NODE * ) 0 ) last->from=tmp;
                    196:                last=tmp;
                    197:                tmp->datump=tdp;
                    198:                tmp->prob=tprob;
                    199:                tmp->ldad=tmp->rdad=tmp->kid=(NODE *) 0;
                    200:        }
                    201:        tmp->from = ((NODE *)0);
                    202:        return first;
                    203: }
                    204: static int 
                    205: compar(a,b)
                    206: NODE ** a, ** b;
                    207: {
                    208:        if ( (*a)->prob > (*b)->prob ) return 1;
                    209:        if ( (*a)->prob < (*b)->prob ) return -1;
                    210:        return 0;
                    211: }
                    212: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.