为什么霍夫曼代码的节点排序不正确? C

时间:2018-10-20 10:50:05

标签: c arrays tree heap huffman-code

我正在尝试调试我的霍夫曼代码,并发现当我调用buildHuffmanTree并使用我在下面注释掉的打印功能打印我的minHeap的节点时,出现分段错误:11因为我只有5当我期望霍夫曼树中的11个节点由原来的6个字母组成时,加上5个内部节点(它们的频率之和)。有人可以帮我找出解决方法吗?

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>

    #define SIZE 100000

    char arr[SIZE];
    int  freq[SIZE]; 
    int  arr2[SIZE]; 

    int qTop = 0;
    int size=0;

    struct node{

        char data;
        int frequency;
        struct node* left;
        struct node* right;
    };

    struct node* PQ[SIZE];

    struct node* newNode(char data, int frequency){

        struct node* t = (struct node*)malloc(sizeof(struct node)); 
        t->data = data;
        t->frequency= frequency; 
        t->left = NULL; 
        t->right = NULL; 
        return (t); 
    }



void minHeapify(struct node* PQ[], int x){

    int frequency = PQ[x]->frequency;
    char data = PQ[x]->data;
    int i=x;  //the current node
    int j= 2*i; //the left node
    while(j<=qTop){
        if (j<qTop && (PQ[j+1]->frequency < PQ[j]->frequency)){
            j=j+1; //the right node
        }
        if (PQ[j]->frequency < frequency){
            PQ[i]->frequency = PQ[j]->frequency;
            PQ[i]->data = PQ[j]->data;
            i=j;
            j=2*i;
        } else{
            break;
        }
    }

}

void push(struct node* PQ[], struct node* node){

    if (qTop==SIZE){
        printf("PQ OVERFLOW \n");
    } else{
        qTop=qTop+1;
        int i = qTop;
        int j = (int)(i/2);
        while (i > 1 && PQ[j]->frequency > node->frequency){
            PQ[i] = PQ[j];
            i = j;
            j = (int)(i/2);
        }
        PQ[i] = node;
    }
}

struct node* pop(struct node* PQ[]){

    if (qTop==0){
        printf("PQ UNDERFLOW \n");
        return NULL;
    } else{
        struct node* node = PQ[1];
        PQ[1] = PQ[qTop];
        qTop = qTop - 1;
        minHeapify(PQ,1);
        return node;
    }

}

void printCodes(struct node* root, int arr2[], int top) {  

    if (root->left) { 
        arr2[top] = 0; 
        printCodes(root->left, arr2, top + 1); 
    } 

    if (root->right) { 
        arr2[top] = 1; 
        printCodes(root->right, arr2, top + 1); 
    } 

    if (root->left == NULL && root->right == NULL) { 
        printf("%c: ", root->data); 
        for (int i = 0; i < top; i++){
            printf("%d", arr2[i]); 
        } 
        printf("\n"); 

    } 
}

void buildHuffmanTree(char arr[], int freq[]){

    for (int i=0;i<strlen(arr);i++){
        struct node* node = newNode(arr[i],freq[i]);
        push(PQ,node);
        size++;
    }
    int PQsize=0;
    for (int i=1; i<size;i++){
        PQsize++;
        struct node* node2 = newNode('!',0);
        node2->left = pop(PQ);
        node2->right = pop(PQ);
        struct node* nodeL=node2->left;
        struct node* nodeR=node2->right;
        node2->frequency = nodeL->frequency + nodeR->frequency;
        push(PQ,node2);
    }

    /*
    for (int i=1;i<PQsize,i++){
        printf("%c:%d \n",PQ[i]->data,PQ[i]->frequency);
    }
    */
    struct node* root= pop(PQ);
    int top=0;
    printCodes(root,arr2,top);
}

int main(){

    char arr[] = "abcdef"; 
    int freq[] = { 5, 9, 12, 13, 16, 45 }; 

    buildHuffmanTree(arr,freq);

    return 0;
}

运行注释掉的打印功能时,我得到:

!:100 
!:55 
!:30 
e:16 
d:13 
b:9 
Segmentation fault: 11

结果是我的编码错误并且程序输出:

c: 00
a: 010
b: 011
!: 10
!: 110
e: 111

代替:

a: 1100
b: 1101
c: 100
d: 101
e: 111
f: 0

请帮助我理解为什么将节点插入minHeap后所有节点都变得混乱。谢谢。

1 个答案:

答案 0 :(得分:1)

PQ是一个指针数组。首次调用push时,没有为这些指针分配任何内容。 push执行:

    qTop=qTop+1;
    int i = qTop;
    int j = (int)(i/2);
    while (i > 0 && PQ[j]->frequency > node->frequency){

在这一点上,i大于零,但是尚未为PQ[j]分配值。从现在开始,程序的行为是不确定的。