Huffman编码

#define MAX_WEIGHT 255

typedef struct 
{
    int weight;
    int traverseMark;
    int parent, lchild, rchild;
}HTNode, *HuffmanTree;
typedef char ** HuffmanCode;
HuffmanTree HT = nil;
HuffmanCode HC = nil;
int *markSelect = nil;
int min1 = 0;
int min2 = 0;
void HTselect(int length)
{
    int min = MAX_WEIGHT;
    for (int i = 0; i < length; i++)
    {
        if ((HT[i].weight < min)&&(markSelect[i] == 0))
        {
            min = HT[i].weight;
            min1 = i;
        }
    }
    
    markSelect[min1] = 1;

    min = MAX_WEIGHT;
    for (int i = 0; i < length; i++)
    {
        if ((HT[i].weight < min)&&(markSelect[i] == 0))
        {
            min = HT[i].weight;
            min2 = i;
        }
    }
    markSelect[min2] = 1;

    return;
}
void HuffmanCoding(int *w, int n)
{
    if (n <= 1)
    {
        return;
    }
    int m = 2*n - 1;
    HT = (HuffmanTree)malloc(m * sizeof(HTNode));
    
    //used in HTSelect for marking the traversed node;
    markSelect = (int *)malloc(m * sizeof(int));
    for (int q = 0; q < m; q++)
    {
        markSelect[q] = 0;
    }
    
    //init the node weight and status
    HuffmanTree p = HT;
    int i = 0;
    for (;i < n; ++i, ++p)
    {
        p->weight = w[i];
        p->parent = MAX_WEIGHT;
        p->lchild = MAX_WEIGHT;
        p->rchild = MAX_WEIGHT;
        p->traverseMark = 0;
    }
    for (; i < m; ++i, ++p)
    {
        p->weight = 0;
        p->parent = MAX_WEIGHT;
        p->lchild = MAX_WEIGHT;
        p->rchild = MAX_WEIGHT;
        p->traverseMark = 0;
    }
    
    //constuct the Huffman tree
    //1...n is leaf nodes
    //n+1....m is not leaf nodes
    for (int j = n; j < m; j++)
    {
        HTselect(j);
        //
        HT[min1].parent = j;
        HT[min2].parent = j;
        HT[j].lchild = min1;
        HT[j].rchild = min2;
        HT[j].weight = HT[min1].weight + HT[min2].weight;
    }
    //print the Huffman tree
    p = HT;
    for (int j = 0; j < m; p++, j++)
    {
        NSLog(@"%d, %d, %d, %d", p->weight, p->parent, p->lchild, p->rchild);
    }
}


//get the Huffman code from the Huffman root to the leaf
void HuffmanGetCode(int n)
{
    int p = 2*n - 1 - 1;
    HC = (HuffmanCode)malloc(n * sizeof(char *));
    char *cd = (char *)malloc(n * sizeof(char));
    int cdlen = 0;
    while (p != MAX_WEIGHT)
    {
        if (HT[p].traverseMark == 0)
        {
            HT[p].traverseMark = 1;
            if (HT[p].lchild != MAX_WEIGHT)
            {
                p = HT[p].lchild;
                cd[cdlen++] = '0';
            }
            else {
                HC[p] = (char *)malloc((cdlen + 1) *sizeof(char));
                cd[cdlen] = '\0';
                strcpy(HC[p], cd);
            }
            
        }
        else if (HT[p].traverseMark == 1)
        {
            HT[p].traverseMark = 2;
            if (HT[p].rchild != MAX_WEIGHT)
            {
                p = HT[p].rchild;
                cd[cdlen++] = '1';
            }
        }
        else
        {
            cdlen--;
            HT[p].traverseMark = 0;
            p = HT[p].parent;

        }
    }
    for (int i = 0; i < n; i++)
    {
        printf("%s\n", HC[i]);
    }
}

//decode the information using the Huffman tree
void HTDecode(int *code, int elementCount, int n)
{
    int i = 0;
    int j = 0;
    int p = 2*elementCount - 1 - 1;
    int decode[MAX_WEIGHT]; 

    while (i < n)
    {
        if (code[i] == 0)
        {
            if (HT[p].lchild != MAX_WEIGHT)
            {
                i++;
                p = HT[p].lchild;
            }
            else
            {
                decode[j++] = p;
                p = 2*elementCount - 1 - 1;
            }
        }
        else
        {
            if (HT[p].rchild != MAX_WEIGHT)
            {
                i++;
                p = HT[p].rchild;
            }
            else
            {
                decode[j++] = p;
                p = 2*elementCount - 1 - 1;
            }
        }
    }
    decode[j] = p;
    for(int i = 0; i <= j; i++)
    {
        printf("%d", decode[i]);
    }
    
}

-(void)main
{
    int weight[5] = {4,5,8,9,12};
    HuffmanCoding(weight, 5);
    HuffmanGetCode(5);
    int code[12] = {0,0,1,0,0,0,1,1,1,1,0,1};
    HTDecode(code, 5, 12);
}


你可能感兴趣的:(struct,tree)