第五届图灵杯1872PJ的情书,大致运用到哈夫曼树,代码尽量用C语言,简单易懂一点,多加点注释

2025-06-29 01:26:59
推荐回答(1个)
回答1:

#include 
#include 
#include 
#include 
#include 
#include 

#define nonull
#define nullable
#define nonzero

#define TestLoveLetterContent "I Love You So Much"
#define TableSize ('Z' - 'A' + 1 + 'z' - 'a' + 1)
#define CharToTableIndex(char) ((char) >= 'A' && (char) <= 'Z' ? (char) - 'A' : (char) >= 'a' && (char) <= 'z' ? (char) - 'a' + 'Z' - 'A' + 1 : (raise(SIGINT), 0))
#define TableIndexToChar(index) ((index) >=0 && (index) <= 'Z' - 'A' ? 'A' + (index) : (index) >= 'Z' - 'A' + 1 &&  (index) <= 'Z' - 'A' + 1 + 'z' - 'a' ? (index) - 'Z' + 'A' - 1 + 'a' : (raise(SIGINT), 0))

typedef struct node *Node;

Node CreateNode(size_t nonzero arrayLength, size_t index, bool beginWith);
void DestroyNode(Node node);
const bool *NodeGetRepresentation(Node nonull node, size_t * nonull length);
const char *GetLoveLetter(void);

int main(int argc, char *argv[])
{
    size_t table[TableSize] = {0};
    const char *loveLetter = GetLoveLetter();
    const char *current = loveLetter;
    while(*current++ != '\0')
        if(current[-1] != ' ')
            table[CharToTableIndex(current[-1])]++;
    
    size_t charArrSize = 0;
    size_t charIndexArr[TableSize];
    bool allTableValueZero;
    do
    {
        allTableValueZero = true;
        size_t biggest = 0;
        for(size_t index = 0; index < TableSize; index++)
            if(table[index] > 0)
            {
                allTableValueZero = false;
                if(table[biggest] < table[index])
                    biggest = index;
            }
        if(!allTableValueZero)
        {
            charIndexArr[charArrSize++] = biggest;
            table[biggest] = 0;
        }
    }while(!allTableValueZero);
    
    Node nodeArr[TableSize];
    
    for(size_t index = 0; index < charArrSize; index++)
        nodeArr[index] = CreateNode(charArrSize, index, true);
    
    fprintf(stdout, "How to Read:\n");
    for(size_t index = 0; index < charArrSize; index++)
    {
        fprintf(stdout, "%c:", (int)TableIndexToChar(charIndexArr[index]));
        size_t length;
        const bool *representation = NodeGetRepresentation(nodeArr[index], &length);
        for(size_t index = 0; index < length; index++)
            if(representation[index])
                putc('1', stdout);
            else
                putc('0', stdout);
        putc('\n', stdout);
    }
    
    fprintf(stdout, "LOVE LETTER:\n");
    
    current = loveLetter;
    
    while (*current++ != '\0')
        if(current[-1] == ' ')
            putc(' ', stdout);
        else
        {
            size_t currentCharIndex = CharToTableIndex(current[-1]);
            Node currentNode = NULL;
            for(size_t index = 0; index < charArrSize; index++)
                if(charIndexArr[index] == currentCharIndex)
                {
                    currentNode = nodeArr[index];
                    break;
                }
            size_t length;
            const bool *currentRepresentation = NodeGetRepresentation(currentNode, &length);
            for(size_t index = 0; index < length; index++)
                if(currentRepresentation[index])
                    putc('1', stdout);
                else
                    putc('0', stdout);
        }
    return 0;
}

const char *GetLoveLetter(void)
{
    return TestLoveLetterContent;
}

struct node
{
    bool *representation;
    size_t length;
};

Node CreateNode(size_t nonzero arrayLength, size_t index, bool beginWith)
{
    assert(arrayLength != 0);
    assert(index < arrayLength);
    
    bool *representation;
    bool isLast = index == arrayLength - 1;
    size_t representationLength = isLast ? index : index + 1;
    
    if((representation = malloc(representationLength * sizeof(bool))) != NULL)
    {
        for(size_t each = 0; each < representationLength; each++)
            representation[each] = !beginWith;
        if(!isLast) representation[representationLength - 1] = beginWith;
        Node result;
        if((result = malloc(sizeof(struct node))) != NULL)
        {
            result->representation = representation;
            result->length = representationLength;
            return result;
        }
        free(representation);
    }
    return NULL;
}

void DestroyNode(Node node)
{
    if(node == NULL) return;
    free(node->representation);
    free(node);
}

const bool *NodeGetRepresentation(Node nonull node, size_t * nonull length)
{
    assert(node != NULL);
    assert(length != NULL);
    *length = node->length;
    return node->representation;
}