⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hfmdaima.txt

📁 自适应哈夫曼编码
💻 TXT
字号:

#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#define MAXTEXT 100
#define MAXNODE 100
#define MAXCODE 100

typedef struct Node/*树结点*/
{
    struct Node *parent;
    struct Node *lcld;
    struct Node *rcld;
    char c;/*字符*/
    int freq;/*频率*/
    char code[MAXCODE];/*字符的哈夫曼编码*/
}Node;

void GradationVisit();
char text[MAXTEXT];/*记录输入字符串*/
Node *root;
Node* allNode[MAXNODE];/*存储所有结点的地址,大大节约遍历的开销*/
int NodeNum;/*当前树的结点数*/
Node *NEW;

/*输入字符*/
void Input ()
{
    int i = 0;
    char c = 0;
    printf ("Please input the text (end with '$') !\n");
    
    scanf ("%c",&c);
    while (i<MAXTEXT-2 && c!='$')
    {
        text[i] = c; 
        i++;
        scanf ("%c",&c);
    }
    text[i] = '$';
    text[i+1] = '\0';
}

/*找具有频率n的在树root中的最远结点*/
Node* FindFarestNode (int freq)
{
 int i = 0;
    GradationVisit(); 
    while (i < NodeNum)
    {
        /*由于采取了特殊的层次遍历策略,第一次找到的肯定就是最远的*/
        if (allNode[i]->freq == freq)
            return allNode[i];
        i++;
    }
    return NULL;
}

/*查找存储字符c的结点,如果不存在,返回NULL*/
Node* FindNode (char c)
{ 
 int i = 0;
    GradationVisit();
    while (i < NodeNum)
    {
        if (allNode[i]->c==c && allNode[i]!=NEW)
            return allNode[i];
        i++;
    }
    return NULL;
}

/*对树进行层次遍历,保存在allNode里*/
void GradationVisit ()
{
    /*为了方便查找具有频率n的在树root中的最远结点
    采用自顶而下,自右而左的遍历顺序*/
    
    /*至少有一个元素root*/
    int curr = 0;
    int len = 0;
    NodeNum = 1;
    allNode[0] = root;
    allNode[0]->code[0] = '\0';
    
    while (curr < NodeNum)
    {
        if (allNode[curr]->rcld != NULL)
        {
            strcpy(allNode[curr]->rcld->code,allNode[curr]->code);
            len = strlen(allNode[curr]->rcld->code);
            allNode[curr]->rcld->code[len] = '1';
            allNode[curr]->rcld->code[len+1] = '\0';
            allNode[NodeNum] = allNode[curr]->rcld;
            NodeNum++;
        }    
        if (allNode[curr]->lcld != NULL)
        {
            strcpy(allNode[curr]->lcld->code,allNode[curr]->code);
            len = strlen(allNode[curr]->lcld->code);
            allNode[curr]->lcld->code[len] = '0';
            allNode[curr]->lcld->code[len+1] = '\0';
            allNode[NodeNum] = allNode[curr]->lcld;
            NodeNum++;
        }    
        curr++;
    }
}

/*打印结点编码*/
void PrintTree ()
{
 int i = 0;
    GradationVisit();/*相当于对结点进行按层次的排序*/
    printf("\n");
    /*按层次打印结点编码*/
    while (i < NodeNum)
    {
        if (allNode[i]->lcld==NULL && allNode[i]->rcld==NULL && allNode[i]->c!=0)/*叶子结点*/
            printf("c = %c, freq = %d, code = %s\n",allNode[i]->c,allNode[i]->freq,allNode[i]->code);
        i++;
    }
}

/*交换子树*/
void Swap(Node *n1, Node *n2)
{
    /*may be there is error hear*/
    Node *n1Parent = n1->parent;
    Node *n2Parent = n2->parent;
    
    if (n1Parent->lcld == n1)
        n1Parent->lcld = n2;
    else
        n1Parent->rcld = n2;
        
    if (n2Parent->lcld == n2)
        n2Parent->lcld = n1;
    else
        n2Parent->rcld = n1;
        
    n1->parent = n2Parent;
    n2->parent = n1Parent;
}

/*输入一个字符,调整树*/
void AdjustTree (char c)
{
 int freq;
    Node *tempNode1;
    Node *tempNode2;
    Node *newNode; 

    Node *n = FindNode(c);
    if (n == NULL)/*c不在树上*/
    {
        /*新增结点*/
        n = (Node*)malloc(sizeof(Node));
        n->c = c;
        n->freq = 1;
        n->lcld = n->rcld = NULL;
        n->parent = NEW;
        
        newNode = (Node*)malloc(sizeof(Node));/*新的NEW结点*/
        newNode->c = 0;
        newNode->freq = 0;
        newNode->lcld = newNode->rcld = NULL;
        newNode->parent = NEW;
        
        NEW->lcld = newNode;
        NEW->rcld = n;
        
        NEW = newNode;
    }
    else/*c在树上*/
        n->freq++;
    
    /*调整树*/
 freq = n->freq;
    tempNode1 = n;
    tempNode2;
    
    while (tempNode1 != root)
    {
        tempNode2 = FindFarestNode(freq-1);
        if (tempNode2!=tempNode1->parent && tempNode2!=NULL && tempNode2!=NEW)
            Swap(tempNode1,tempNode2);
        tempNode1->parent->freq++;
        tempNode1 = tempNode1->parent;
        freq = tempNode1->freq;
    }
}

/*对文本text进行自适应哈夫曼编码*/
void Encoding ()
{
    int i = 0;
    while (text[i] != '$')/*每次调整一个字符,输出字符编码*/
    {
        AdjustTree(text[i]);
        PrintTree();
        i++;
    }
}

/*销毁树root*/
void Release ()
{
    int i = 0;
    while (i < NodeNum)
    {
        free(allNode[i]);/*allNode存放了所有结点的地址*/
        i++;
    }
}

/*初始化*/
void Init ()
{
 int i = 0;
    root = (Node*)malloc(sizeof(Node));
    root->c = 0;
    root->freq = 0;
    root->lcld = root->rcld = root->parent = NULL;
    NEW = root;
    NodeNum = 0;
      
    while (i < MAXNODE)
    {
        allNode[i] = NULL;
        i++;
    }
}

int main ()
{
    Init();
    Input();
    Encoding();
    Release();
    return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -