• [C] 哈夫曼算法


    来源:网络

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

    /*声明两种链表结构----start*/
    struct node_a{ /*链表1-----作用:用来统计文件中字符的个数和种类(通过count)*/
    char data;
    int count;
    struct node_a *next;
    };
    typedef
    struct node_a node,*list;
    list head
    =NULL;

    struct nodeb{ /*链表2-----作用:用来建立用相应的编码代替字符的新文件*/
    char data;
    struct nodeb *next;
    };
    typedef
    struct nodeb node_b,*list_b; /*jiang bianma xieru wenjian*/
    list_b head_b
    =NULL;
    /*声明两种链表结构----end*/

    /*哈夫曼算法种相关的3种结构的声明-----start*/
    struct forest{
    float weight;
    int root;
    };
    struct alphabet{
    char symbol;
    float probability;
    int leaf;
    char *bianma;
    };
    struct tree{
    int lchild;
    int rchild;
    int parent;
    };
    typedef
    struct tree *tree_ptr,tree_node;
    typedef
    struct forest *forest_ptr,forest_node;
    typedef
    struct alphabet *alphabet_ptr,alphabet_node;
    tree_ptr tree1;
    forest_ptr forest1;
    alphabet_ptr alphabet1;
    int lasttree,lastnode;
    int least,second;
    /*哈夫曼算法种相关的3种结构的声明-----end*/

    /**************stack difination start****************/
    struct stacknode{
    char *bian_ma;
    struct stacknode *next;
    };
    typedef
    struct stacknode stack_node;
    typedef stack_node
    *link;
    link top
    =NULL;

    void push(char *item){
    link p;
    if(top!=NULL){
    p
    =(link)malloc(sizeof(stack_node));
    if(p==NULL){
    printf(
    "Memory allocation error!");
    return;
    }
    p
    ->bian_ma=item;
    p
    ->next=top;
    top
    =p;
    }
    else{
    top
    =(link)malloc(sizeof(stack_node));
    if(!top){
    printf(
    "Memory allocation error!");
    return;
    }
    top
    ->bian_ma=item;
    top
    ->next=NULL;
    }
    }

    void pop(void){
    link p;
    p
    =top;
    top
    =top->next;
    free(p);
    }

    void makenull(void){
    while(top!=NULL)
    pop();
    }

    int empty(){
    if(top==NULL)
    return 1;
    else
    return 0;
    }

    char* tops(void){
    return (top->bian_ma);
    }

    void display_stack(link s){ /*显示栈重的内容*/
    link ptr;
    ptr
    =s;
    while(ptr!=NULL){
    printf(
    "%s",ptr->bian_ma);
    ptr
    =ptr->next;
    }
    }

    /***************************stack__difination is end************************/
    void display(list h){ /*显示链表1*/
    list ptr;
    int i=1;
    ptr
    =h->next;
    while(ptr!=NULL){
    printf(
    "%d,%c,%d\n",i,ptr->data,ptr->count);
    i
    ++;
    ptr
    =ptr->next;
    }
    }
    void display_b(list_b h){ /*显示链表2*/
    list_b ptr;
    int i=1;
    ptr
    =h->next;
    while(ptr!=NULL){
    printf(
    "%d,%c\n",i,ptr->data);
    i
    ++;
    ptr
    =ptr->next;
    }
    }

    void insert(char item){ /*用于插入元素以建立链表1*/
    list temp,ptr;
    int flag;
    ptr
    =head->next;
    if(ptr==NULL){
    head
    ->next=(list)malloc(sizeof(node));
    head
    ->next->data=item;
    head
    ->next->count=1;
    head
    ->next->next=NULL;
    }
    else{
    while(ptr!=NULL){
    if(ptr->data==item){
    ptr
    ->count=ptr->count+1;
    flag
    =1;
    }
    ptr
    =ptr->next;
    }
    ptr
    =head;
    if(flag==1)
    return;
    else{
    temp
    =ptr->next;
    ptr
    ->next=(list)malloc(sizeof(node));
    ptr
    ->next->data=item;
    ptr
    ->next->count=1;
    ptr
    ->next->next=temp;
    }
    }
    }

    void insert_b(char item){ /*插入元素以建立链表2*/
    list_b ptr_b, temp_b;
    ptr_b
    =head_b;
    if(ptr_b->next==NULL){
    head_b
    ->next=(list_b)malloc(sizeof(node_b));
    head_b
    ->next->data=item;
    head_b
    ->next->next=NULL;
    }
    else{
    while(ptr_b->next!=NULL){
    ptr_b
    =ptr_b->next;
    }
    ptr_b
    ->next=(list_b)malloc(sizeof(node_b));
    ptr_b
    ->next->data=item;
    ptr_b
    ->next->next=NULL;
    }
    }

    void search(void){ /*搜索文件并将文件中的数据分别存入作用不同的链表中*/
    FILE
    *fp;
    list ptr;
    char ch;
    if((fp=fopen("test.txt","r"))==NULL)
    printf(
    "Reading error!\n");
    while(!feof(fp)){
    ch
    =getc(fp);
    if(ferror(fp)){
    printf(
    "error!\n");
    break;
    }
    if(ch==EOF)
    break;
    insert(ch);
    /*插入元素进链表1*/
    insert_b(ch);
    /*插入元素进链表2*/
    }
    printf(
    "\n");
    fclose(fp);
    }

    void display_struct(int n){ /*显示哈夫曼算法中的3个结构树组 */
    int i=0;
    printf(
    "\n\n=======================================\n\n");
    printf(
    "FOREST_STRUCT_ARRY :\n\n\n");
    for(i=0;i<=n;i++){
    printf(
    "%f,%d\n",forest1[i].weight,forest1[i].root);
    }
    getch();
    printf(
    "\n\nALPHABET_STRUCT_ARRY :\n\n\n");
    for(i=0;i<=n;i++){
    printf(
    "%f,%d,%c\n",alphabet1[i].probability,alphabet1[i].leaf,alphabet1[i].symbol);
    }
    getch();
    printf(
    "\n\nTREE_STRUCT_ARRY :\n\n\n");
    for(i=0;i<=2*n-1;i++)
    printf(
    "%d,%d,%d\n",tree1[i].lchild,tree1[i].rchild,tree1[i].parent);
    printf(
    "\n\n======================================\n\n");
    getch();
    }

    int init_struct(void){ /*初始化哈夫曼算法中3种结构数组*/
    list ptr;
    float count=.0;
    int i=1,n=0;
    ptr
    =head->next;
    while(ptr!=NULL){
    count
    =ptr->count+count;
    n
    ++;
    ptr
    =ptr->next;
    }
    ptr
    =head->next;
    forest1
    =(forest_ptr)malloc(sizeof(forest_node)*n+sizeof(forest_node));
    alphabet1
    =(alphabet_ptr)malloc(sizeof(alphabet_node)*n+sizeof(alphabet_node));
    tree1
    =(tree_ptr)malloc(sizeof(tree_node)*n*2-sizeof(tree_node));
    forest1[
    0].weight=alphabet1[0].probability=0.0;
    forest1[
    0].root=alphabet1[0].leaf=0;
    alphabet1[
    0].symbol='0';
    while(ptr!=NULL){
    forest1[i].weight
    =alphabet1[i].probability=ptr->count/count;
    forest1[i].root
    =alphabet1[i].leaf=i;
    alphabet1[i].symbol
    =ptr->data;
    i
    ++;
    ptr
    =ptr->next;
    }
    for(i=0;i<=2*n-1;i++){
    tree1[i].lchild
    =0;
    tree1[i].rchild
    =0;
    tree1[i].parent
    =0;
    }
    return n;
    }

    void creat(void){ /*创建正文文件test.txt*/
    FILE
    *fp,*out;
    char ch;
    if((fp=fopen("test.txt","r++"))==NULL)
    printf(
    "Creat error!\n");
    printf(
    "Input the data:\n");
    ch
    =getch();
    putch(ch);
    while(ch!='#'){
    putc(ch,fp);
    ch
    =getch();
    putch(ch);
    }
    fclose(fp);
    }

    void creat_bianma(int number){ /*根据哈夫曼算法建立文件中各种字符对应的编码*/
    int i,j,n;
    int p;
    char *bm=malloc(sizeof(char)*number);
    for(n=1;n<=number;n++){
    j
    =i=n;
    makenull();
    p
    =tree1[i].parent;
    while(tree1[p].parent!=0){
    if(tree1[p].lchild==i)
    push(
    "0");
    else
    push(
    "1");
    i
    =p;
    p
    =tree1[p].parent;
    }

    if(tree1[p].lchild==i)
    push(
    "0");
    else
    push(
    "1");
    strcpy(bm,
    " "); /*目的:使创建编码文件中的各编码中间存在间隔*/
    while(!empty()){
    strcat(bm,tops());
    pop();
    }
    alphabet1[j].bianma
    =malloc(sizeof(char)*number);
    strcpy(alphabet1[j].bianma,bm);
    printf(
    "\n%c:%s",alphabet1[j].symbol,alphabet1[j].bianma); /*打印出相应的编码*/
    getch();
    }
    }


    void write_new_file(int number){ /*根据相应的编码重新建立编码文件*/
    FILE
    *fp;
    list_b ptr;
    int i;
    char *ch=malloc(sizeof(char)*number);
    ptr
    =head_b->next;
    if((fp=fopen("bianma.txt","w"))==NULL)
    printf(
    "Write in a new file error!");
    else{
    while(ptr!=NULL){
    for(i=1;i<=number;i++){
    if(ptr->data==alphabet1[i].symbol){
    strcpy(ch,alphabet1[i].bianma);
    fputs(ch,fp);
    }
    }
    ptr
    =ptr->next;
    }
    }
    fclose(fp);
    }


    void main(void){
    int i,num;
    char ch;
    void huffman(void);
    void lightones();
    head
    =(list)malloc(sizeof(node));
    head
    ->next=NULL;
    head
    ->data='\0';
    head
    ->count=0;
    head_b
    =(list_b)malloc(sizeof(node_b));
    head_b
    ->data='\0';
    head_b
    ->next=NULL;
    do{
    system(
    "cls");
    creat();
    search();
    printf(
    "\nlianbiao1:\n");
    display(head);
    /*显示链表1*/
    getch();
    printf(
    "\nlianbiao2:\n");
    display_b(head_b);
    getch();
    num
    =init_struct();
    printf(
    "\n");
    printf(
    "The 3 init_struct of huffman?\n");
    display_struct(num);
    /*显示初始化的哈夫曼书的相关3个结构数组*/
    lastnode
    =num;
    lasttree
    =num;
    huffman();
    printf(
    "Now the 3 struct through huffman shuanfa\n");
    display_struct(num);
    /*显示哈夫曼树中相关的3种结构(经过哈夫曼算法处理)*/
    printf(
    "\nThe bian_ma is:\n");
    creat_bianma(num);
    write_new_file(num);
    printf(
    "\nDo you want to re_try(y/n)?");
    ch
    =getchar();
    }
    while(ch=='y');
    }

    /*哈夫曼算法-----defination_start*/
    void lightones(void){
    int i;
    if(forest1[1].weight<=forest1[2].weight){
    least
    =1;
    second
    =2;
    }
    else{
    least
    =2;
    second
    =1;
    }
    for(i=3;i<=lasttree;i++)
    if(forest1[i].weight<forest1[least].weight){
    second
    =least;
    least
    =i;
    }
    else
    if(forest1[i].weight<forest1[second].weight)
    second
    =i;
    }

    int creat_tree(int lefttree,int righttree){
    lastnode
    =lastnode+1;
    tree1[lastnode].lchild
    =forest1[lefttree].root;
    tree1[lastnode].rchild
    =forest1[righttree].root;
    tree1[lastnode].parent
    =0;
    tree1[forest1[lefttree].root].parent
    =lastnode;
    tree1[forest1[righttree].root].parent
    =lastnode;
    return(lastnode);
    }

    void huffman(void){
    int i,j;
    int newroot;
    while(lasttree>1){
    lightones();
    i
    =least;
    j
    =second;
    newroot
    =creat_tree(i,j);
    forest1[i].weight
    =forest1[i].weight+forest1[j].weight;
    forest1[i].root
    =newroot;
    forest1[j]
    =forest1[lasttree];
    lasttree
    =lasttree-1;
    }
    }
  • 相关阅读:
    ES6的Generator函数
    2017年要学习的三个CSS新特性
    移动端H5页面遇到的问题总结
    移动端布局解决方案+神器
    利用HTML5的devicemotion事件实现手机摇一摇抽奖,年会抽奖
    JavaScript 中 for 循环
    HTML DOM对象的属性和方法介绍(原生JS方法)
    初识JSON
    让你的WizFi250适应各种气候
    JAVA复习2 JAVA开发环境配置
  • 原文地址:https://www.cnblogs.com/hcbin/p/1711419.html
Copyright © 2020-2023  润新知