的二进制字符串。

压缩代码:

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

#define MAX_TREE_HT 100
#define FIXED_LENGTH 8

struct MinHeapNode {
    char data;
    unsigned freq;
    struct MinHeapNode *left, *right;
};

struct MinHeap {
    unsigned size;
    unsigned capacity;
    struct MinHeapNode** array;
};

struct MinHeapNode* newNode(char data, unsigned freq)
{
    struct MinHeapNode* temp =
          (struct MinHeapNode*) malloc(sizeof(struct MinHeapNode));

    temp->left = temp->right = NULL;
    temp->data = data;
    temp->freq = freq;

    return temp;
}

struct MinHeap* createMinHeap(unsigned capacity)
{
    struct MinHeap* minHeap =
         (struct MinHeap*) malloc(sizeof(struct MinHeap));

    minHeap->size = 0;
    minHeap->capacity = capacity;
    minHeap->array =
         (struct MinHeapNode**)malloc(minHeap->capacity * sizeof(struct MinHeapNode*));
    return minHeap;
}

void swapMinHeapNode(struct MinHeapNode** a, struct MinHeapNode** b)
{
    struct MinHeapNode* t = *a;
    *a = *b;
    *b = t;
}

void minHeapify(struct MinHeap* minHeap, int idx)
{
    int smallest = idx;
    int left = 2 * idx + 1;
    int right = 2 * idx + 2;

    if (left < minHeap->size &&
        minHeap->array[left]->freq < minHeap->array[smallest]->freq)
      smallest = left;

    if (right < minHeap->size &&
        minHeap->array[right]->freq < minHeap->array[smallest]->freq)
      smallest = right;

    if (smallest != idx) {
        swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]);
        minHeapify(minHeap, smallest);
    }
}

int isSizeOne(struct MinHeap* minHeap)
{
    return (minHeap->size == 1);
}

struct MinHeapNode* extractMin(struct MinHeap* minHeap)
{
    struct MinHeapNode* temp = minHeap->array[0];
    minHeap->array[0] = minHeap->array[minHeap->size - 1];
    --minHeap->size;
    minHeapify(minHeap, 0);
    return temp;
}

void insertMinHeap(struct MinHeap* minHeap, struct MinHeapNode* minHeapNode)
{
    ++minHeap->size;
    int i = minHeap->size - 1;
    while (i && minHeapNode->freq < minHeap->array[(i - 1)/2]->freq) {
        minHeap->array[i] = minHeap->array[(i - 1)/2];
        i = (i - 1)/2;
    }
    minHeap->array[i] = minHeapNode;
}

void buildMinHeap(struct MinHeap* minHeap)
{
    int n = minHeap->size - 1;
    int i;
    for (i = (n - 1) / 2; i >= 0; --i)
        minHeapify(minHeap, i);
}

void printArr(int arr[], int n, FILE *fp)
{
    int i;
    for (i = 0; i < n; ++i)
        fprintf(fp, "%d", arr[i]);
}

int isLeaf(struct MinHeapNode* root)
{
    return !(root->left) && !(root->right) ;
}

struct MinHeap* createAndBuildMinHeap(char data[], int freq[], int size)
{
    struct MinHeap* minHeap = createMinHeap(size);

    for (int i = 0; i < size; ++i)
        minHeap->array[i] = newNode(data[i], freq[i]);

    minHeap->size = size;
    buildMinHeap(minHeap);

    return minHeap;
}

struct MinHeapNode* buildHuffmanTree(char data[], int freq[], int size)
{
    struct MinHeapNode *left, *right, *top;

    struct MinHeap* minHeap = createAndBuildMinHeap(data, freq, size);

    while (!isSizeOne(minHeap)) {

        left = extractMin(minHeap);
        right = extractMin(minHeap);

        top = newNode('$', left->freq + right->freq);

        top->left = left;
        top->right = right;

        insertMinHeap(minHeap, top);
    }

    return extractMin(minHeap);
}

void encode(struct MinHeapNode* root, int arr[], int top, FILE *fp)
{
    if (root->left) {
        arr[top] = 0;
        encode(root->left, arr, top + 1, fp);
    }

    if (root->right) {
        arr[top] = 1;
        encode(root->right, arr, top + 1, fp);
    }

    if (isLeaf(root)) {
        fprintf(fp, "%c", root->data);
        printArr(arr, top, fp);
    }
}

void HuffmanCodes(char data[], int freq[], int size, FILE *fp)
{
    struct MinHeapNode* root = buildHuffmanTree(data, freq, size);
    int arr[MAX_TREE_HT], top = 0;

    encode(root, arr, top, fp);
}

void compress(const char *str, const char *filename)
{
    int freq[256] = {0};
    int len = strlen(str);

    for (int i = 0; i < len; ++i)
        ++freq[str[i]];

    FILE *fp = fopen(filename, "wb");

    HuffmanCodes(str, freq, 256, fp);

    fclose(fp);
}

void binaryStringToFile(const char *binaryString, const char *filename)
{
    int len = strlen(binaryString);

    FILE *fp = fopen(filename, "wb");

    int i = 0;
    while (i < len) {
        char byte = 0;
        for (int j = 0; j < FIXED_LENGTH; ++j) {
            byte <<= 1;
            if (binaryString[i] == '1')
                byte |= 1;
            ++i;
        }
        fwrite(&byte, sizeof(char), 1, fp);
    }

    fclose(fp);
}

char* fileToBinaryString(const char *filename)
{
    FILE *fp = fopen(filename, "rb");

    int len = 0;
    char ch;
    while (fread(&ch, sizeof(char), 1, fp))
        ++len;

    rewind(fp);

    char *binaryString = (char*) malloc((len * FIXED_LENGTH + 1) * sizeof(char));
    int i = 0;
    while (fread(&ch, sizeof(char), 1, fp)) {
        for (int j = 0; j < FIXED_LENGTH; ++j) {
            binaryString[i++] = (ch & 0x80) ? '1' : '0';
            ch <<= 1;
        }
    }
    binaryString[i] = '\0';

    fclose(fp);

    return binaryString;
}

void decode(struct MinHeapNode* root, const char *binaryString, int *i, int len, FILE *fp)
{
    if (isLeaf(root)) {
        fprintf(fp, "%c", root->data);
        return;
    }

    if (*i >= len)
        return;

    if (binaryString[*i] == '0')
        decode(root->left, binaryString, i, len, fp);
    else
        decode(root->right, binaryString, i, len, fp);
}

void decompress(const char *filename, const char *outputFilename)
{
    char *binaryString = fileToBinaryString(filename);

    FILE *fp = fopen(outputFilename, "wb");

    int i = 0, len = strlen(binaryString);
    while (i < len) {
        decode(buildHuffmanTree(NULL, NULL, 0), binaryString, &i, len, fp);
    }

    fclose(fp);

    free(binaryString);
}

int main()
{
    compress("qih1786wufg8237fw093h1iffg28fiuw", "compressed.bin");
    decompress("compressed.bin", "decompressed.txt");

    return 0;
}

解压缩代码:

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

#define MAX_TREE_HT 100
#define FIXED_LENGTH 8

struct MinHeapNode {
    char data;
    unsigned freq;
    struct MinHeapNode *left, *right;
};

struct MinHeap {
    unsigned size;
    unsigned capacity;
    struct MinHeapNode** array;
};

struct MinHeapNode* newNode(char data, unsigned freq)
{
    struct MinHeapNode* temp =
          (struct MinHeapNode*) malloc(sizeof(struct MinHeapNode));

    temp->left = temp->right = NULL;
    temp->data = data;
    temp->freq = freq;

    return temp;
}

struct MinHeap* createMinHeap(unsigned capacity)
{
    struct MinHeap* minHeap =
         (struct MinHeap*) malloc(sizeof(struct MinHeap));

    minHeap->size = 0;
    minHeap->capacity = capacity;
    minHeap->array =
         (struct MinHeapNode**)malloc(minHeap->capacity * sizeof(struct MinHeapNode*));
    return minHeap;
}

void swapMinHeapNode(struct MinHeapNode** a, struct MinHeapNode** b)
{
    struct MinHeapNode* t = *a;
    *a = *b;
    *b = t;
}

void minHeapify(struct MinHeap* minHeap, int idx)
{
    int smallest = idx;
    int left = 2 * idx + 1;
    int right = 2 * idx + 2;

    if (left < minHeap->size &&
        minHeap->array[left]->freq < minHeap->array[smallest]->freq)
      smallest = left;

    if (right < minHeap->size &&
        minHeap->array[right]->freq < minHeap->array[smallest]->freq)
      smallest = right;

    if (smallest != idx) {
        swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]);
        minHeapify(minHeap, smallest);
    }
}

int isSizeOne(struct MinHeap* minHeap)
{
    return (minHeap->size == 1);
}

struct MinHeapNode* extractMin(struct MinHeap* minHeap)
{
    struct MinHeapNode* temp = minHeap->array[0];
    minHeap->array[0] = minHeap->array[minHeap->size - 1];
    --minHeap->size;
    minHeapify(minHeap, 0);
    return temp;
}

void insertMinHeap(struct MinHeap* minHeap, struct MinHeapNode* minHeapNode)
{
    ++minHeap->size;
    int i = minHeap->size - 1;
    while (i && minHeapNode->freq < minHeap->array[(i - 1)/2]->freq) {
        minHeap->array[i] = minHeap->array[(i - 1)/2];
        i = (i - 1)/2;
    }
    minHeap->array[i] = minHeapNode;
}

void buildMinHeap(struct MinHeap* minHeap)
{
    int n = minHeap->size - 1;
    int i;
    for (i = (n - 1) / 2; i >= 0; --i)
        minHeapify(minHeap, i);
}

void printArr(int arr[], int n, FILE *fp)
{
    int i;
    for (i = 0; i < n; ++i)
        fprintf(fp, "%d", arr[i]);
}

int isLeaf(struct MinHeapNode* root)
{
    return !(root->left) && !(root->right) ;
}

struct MinHeap* createAndBuildMinHeap(char data[], int freq[], int size)
{
    struct MinHeap* minHeap = createMinHeap(size);

    for (int i = 0; i < size; ++i)
        minHeap->array[i] = newNode(data[i], freq[i]);

    minHeap->size = size;
    buildMinHeap(minHeap);

    return minHeap;
}

struct MinHeapNode* buildHuffmanTree(char data[], int freq[], int size)
{
    struct MinHeapNode *left, *right, *top;

    struct MinHeap* minHeap = createAndBuildMinHeap(data, freq, size);

    while (!isSizeOne(minHeap)) {

        left = extractMin(minHeap);
        right = extractMin(minHeap);

        top = newNode('$', left->freq + right->freq);

        top->left = left;
        top->right = right;

        insertMinHeap(minHeap, top);
    }

    return extractMin(minHeap);
}

void encode(struct MinHeapNode* root, int arr[], int top, FILE *fp)
{
    if (root->left) {
        arr[top] = 0;
        encode(root->left, arr, top + 1, fp);
    }

    if (root->right) {
        arr[top] = 1;
        encode(root->right, arr, top + 1, fp);
    }

    if (isLeaf(root)) {
        fprintf(fp, "%c", root->data);
        printArr(arr, top, fp);
    }
}

void HuffmanCodes(char data[], int freq[], int size, FILE *fp)
{
    struct MinHeapNode* root = buildHuffmanTree(data, freq, size);
    int arr[MAX_TREE_HT], top = 0;

    encode(root, arr, top, fp);
}

void compress(const char *str, const char *filename)
{
    int freq[256] = {0};
    int len = strlen(str);

    for (int i = 0; i < len; ++i)
        ++freq[str[i]];

    FILE *fp = fopen(filename, "wb");

    HuffmanCodes(str, freq, 256, fp);

    fclose(fp);
}

void binaryStringToFile(const char *binaryString, const char *filename)
{
    int len = strlen(binaryString);

    FILE *fp = fopen(filename, "wb");

    int i = 0;
    while (i < len) {
        char byte = 0;
        for (int j = 0; j < FIXED_LENGTH; ++j) {
            byte <<= 1;
            if (binaryString[i] == '1')
                byte |= 1;
            ++i;
        }
        fwrite(&byte, sizeof(char), 1, fp);
    }

    fclose(fp);
}

char* fileToBinaryString(const char *filename)
{
    FILE *fp = fopen(filename, "rb");

    int len = 0;
    char ch;
    while (fread(&ch, sizeof(char), 1, fp))
        ++len;

    rewind(fp);

    char *binaryString = (char*) malloc((len * FIXED_LENGTH + 1) * sizeof(char));
    int i = 0;
    while (fread(&ch, sizeof(char), 1, fp)) {
        for (int j = 0; j < FIXED_LENGTH; ++j) {
            binaryString[i++] = (ch & 0x80) ? '1' : '0';
            ch <<= 1;
        }
    }
    binaryString[i] = '\0';

    fclose(fp);

    return binaryString;
}

void decode(struct MinHeapNode* root, const char *binaryString, int *i, int len, FILE *fp)
{
    if (isLeaf(root)) {
        fprintf(fp, "%c", root->data);
        return;
    }

    if (*i >= len)
        return;

    if (binaryString[*i] == '0')
        decode(root->left, binaryString, i, len, fp);
    else
        decode(root->right, binaryString, i, len, fp);
}

void decompress(const char *filename, const char *outputFilename)
{
    char *binaryString = fileToBinaryString(filename);

    FILE *fp = fopen(outputFilename, "wb");

    int i = 0, len = strlen(binaryString);
    while (i < len) {
        decode(buildHuffmanTree(NULL, NULL, 0), binaryString, &i, len, fp);
    }

    fclose(fp);

    free(binaryString);
}

int main()
{
    compress("qih1786wufg8237fw093h1iffg28fiuw", "compressed.bin");
    decompress("compressed.bin", "decompressed.txt");

    return 0;
}
``
C语言使用Huffman coding压缩字符串qih1786wufg8237fw093h1iffg28fiuw并输出压缩后的字符串解压缩字符串恢复。将字符串压缩成固定长度

原文地址: https://www.cveoy.top/t/topic/cIu6 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录