哈夫曼树编码实现

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

这两行是头文件包含,stdio.h提供了输入输出函数,stdlib.h提供了内存分配等函数。

typedef struct Node{
    char x;
    int num;
    struct Node* next;
}N;

定义了一个名为Node的结构体,并使用typedef为其取别名N。这个结构体用于表示链表中的节点,包含一个字符x、一个表示出现次数的整数num以及指向下一个节点的指针next

typedef struct TreeNode{
    char x;
    int num;
    struct TreeNode* next;
    struct TreeNode* right;
    struct TreeNode* left;
}TN;

定义了一个名为TreeNode的结构体,并使用typedef为其取别名TN。这个结构体用于表示哈夫曼树中的节点,包含一个字符x、一个表示出现次数的整数num、指向左右子节点的指针leftright以及指向下一个节点的指针next

typedef struct path{
    char x;
    struct path* next;
}P;

定义了一个名为path的结构体,并使用typedef为其取别名P。这个结构体可能用于表示哈夫曼编码中的路径,包含一个字符x和指向下一个路径节点的指针next

TN** link2=NULL;
N* link=NULL;
int num=0;

这里声明了三个全局变量。link2是一个指向TreeNode指针的指针,初始化为NULL,可能用于指向一个动态分配的数组,存储哈夫曼树的节点。link是一个指向Node结构体的指针,初始化为NULL,可能用于指向一个链表的头部。num是一个整数,初始化为 0,可能用于记录link2所指向的数组中的节点数量。

void m1(char x){
    if(link!=NULL){
        N* flag=link;
        while(flag!=NULL){
            if(flag->x==x){
                flag->num++;
                return;
            }else{
                flag=flag->next;
            }
        }
    }
    N* w=(N*)malloc(sizeof(N));
    w->x=x;
    w->num=1;
    w->next=link;
    link=w;
}

这个函数m1接收一个字符参数x。如果link不为NULL,则遍历由link指向的链表,查找是否存在字符为x的节点。如果找到,则增加该节点的出现次数并返回。如果没有找到,则创建一个新的节点,将字符x和出现次数 1 存入新节点,并将新节点插入到链表的头部。

void showlink(){
    N* flag=link;
    while(flag!=NULL){
        printf("节点值%c,出现次数%d\n",flag->x,flag->num);
        flag=flag->next;
    }
}

这个函数用于遍历并打印由link指向的链表中的每个节点的字符和出现次数。

void showlink2(){
    TN** flag=link2;
    int k=0;
    for(;k<num;k++){
        printf("节点值%c,出现次数%d\n",flag[k]->x,flag[k]->num);
    }
}

这个函数用于遍历并打印由link2指向的数组中的每个节点的字符和出现次数。

void moveTolink2(){
    N* temp=link;
    num=0;
    while(temp!=NULL){
        num++;
        temp=temp->next;
    }
    link2=(TN**)malloc(sizeof(TN)*num);
    N* flag=link;
    int index=0;
    for(;flag!=NULL;index++){
        TN* w=(TN*)malloc(sizeof(TN));
        w->x=flag->x;
        w->num=flag->num;
        w->right=NULL;
        w->left=NULL;
        link2[index]=w;
        flag=flag->next;    
    }
}

 这个函数用于将由link指向的链表中的节点转移到由link2指向的数组中。首先统计链表中的节点数量并更新num,然后根据num动态分配一个数组的内存空间。接着遍历链表,为每个节点创建一个新的TreeNode结构体,并将其复制到数组中。

TN* getTwo(){
    int min1=link2[0]->num;
    int k=1;
    int index1=0;
    for(;k<num;k++){
        TN* w=link2[k];
        if(w->num<=min1){
            min1=w->num;
            index1=k;
        }
    }TN* w=link2[index1];
    int s=index1;
    for(;s<num;s++){
        link2[s]=link2[s+1];
    }
    num--;
    return w;
}

这个函数用于从由link2指向的数组中找到并返回两个出现次数最小的节点之一。首先找到数组中出现次数最小的节点的索引,然后将该节点从数组中移除(通过将后面的节点向前移动一位,并更新num),最后返回该节点的指针。

void merge(){
    TN* x1=getTwo();
    TN* x2=getTwo();
    TN* x3=(TN*)malloc(sizeof(TN));
    x3->num=x1->num+x2->num;
    x3->left=x1;
    x3->right=x2;
    link2[num]=x3;
    num++;
    while(num!=1){
        merge();
    }
}

这个函数用于构建哈夫曼树。它首先调用getTwo函数两次,获取两个出现次数最小的节点,然后创建一个新的节点,将新节点的出现次数设置为两个子节点出现次数之和,将新节点的左右子节点分别设置为获取的两个节点。接着将新节点添加到由link2指向的数组中,并更新num。然后通过递归调用自身,继续合并节点,直到数组中只剩下一个节点(即哈夫曼树的根节点)。

void showTree(TN* xx,P* path){
    printf("节点num值%d,字符值%c\n",xx->num,xx->x);
    
    if(xx->left!=NULL){
        P* l=(P*)malloc(sizeof(P));
        l->x='0';
        l->next=path;
        
        
        P* r=(P*)malloc(sizeof(P));
        r->x='1';
        r->next=path;
        showTree(xx->left,l);
        showTree(xx->right,r);
    }else{
        printf("路径是:");
        while(path!=NULL){
            printf("%c",path->x);
            path=path->next;
        }
        printf("\n");
    }
}

这个函数用于打印哈夫曼树中的节点信息和对应的哈夫曼编码路径。如果当前节点有子节点,则为左右子节点分别创建一个新的路径节点,并递归调用自身打印子节点的信息和路径。如果当前节点没有子节点(即叶节点),则打印该节点的哈夫曼编码路径。

int main(int argc,char *argv[]){
    char* str="shjlshglkshadhfjssdfdsgksjfdkjhhdfg";
    int k=0;
    for(;;k++){
        if(str[k]=='\0'){
            break;
        }else{
            m1(str[k]);
        }
    }

main函数中,定义了一个字符串str,然后通过一个无限循环遍历这个字符串。对于每个字符,调用m1函数处理该字符,将其添加到由link指向的链表中(如果字符已经存在,则增加出现次数)。当遇到字符串结束符时,退出循环。

    showlink();
    printf("=========\n");
    moveTolink2();
    showlink2();

 打印由link指向的链表中的节点信息,然后调用moveTolink2函数将链表中的节点转移到由link2指向的数组中,并打印数组中的节点信息。

    merge();
    printf("哈夫曼树根节点%d\n",link2[0]->num);
    showTree(link2[0],NULL);

调用merge函数构建哈夫曼树,然后打印哈夫曼树的根节点的出现次数,并调用showTree函数打印哈夫曼树的节点信息和对应的哈夫曼编码路径。

    return 0;
}

main函数返回 0,表示程序正常结束。

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值