|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.