英文字母哈夫曼编码c语言,C语言实现 —— 哈夫曼编码

/*********************************************************************************

*

* 哈夫曼编码

* create: 2020年5月22日 16点42分

* author: LOS(小鱼)

*

* *******************************************************************************

* 本程序所使用的数据结构:

*     1. 双向链表

*     2. 二叉树

* *******************************************************************************

* 提示:

*     同一条件下,所构造的哈夫曼树可以不同,

*     本程序的哈夫曼树同时受字符在文本中的排列顺序和字符的权重影响

*********************************************************************************/

#include

#include

#include

#define OFFSET 35

typedef struct Node{

char value;

int weight;

}Node;

struct{

Node nodes[200];

int size;

} Nodes; // 全部的节点数据存储在这里

typedef struct TreeNode{

Node *node;

struct TreeNode *parent,*left,*right;

}TreeNode;

struct{

TreeNode nodes[200];

int size;

} TreeNodes; // 其实没必要存储,但有得管理是好事

/*********************************************************************************

* 链表需要

********************************************************************************/

typedef struct Elem{

TreeNode *tNode;

struct Elem *prev,*next;

}Elem;

struct{

Elem elems[200];

int size;

} Elems; // 全部的链表数据存储在这里 ( 不销毁, 但会覆盖 )

// 定义链表结构

typedef struct {

struct Elem *first;

struct Elem *last;

int size;

} LinkList;

// 初始化链表

void initLinkList( LinkList *list ){

list->size = 0;

}

// 获取表长

int getSizeL(LinkList *list){

return list->size;

}

void addFirst(LinkList *list,Elem *elem){

if( !getSizeL(list) ){

list->first = elem;

list->last = elem;

}

else {

elem->prev = list->last;

elem->next = list->first;

list->last->next = elem;

list->first->prev = elem;

list->first = elem;

}

list->size++;

}

// 添加元素

void addLast(LinkList *list,Elem *elem){

if( !getSizeL(list) ){

list->first = elem;

list->last = elem;

} else {

elem->prev = list->last;

elem->next = list->first;

list->last->next = elem;

list->first->prev = elem;

list->last = elem;

}

list->size++;

}

Elem * getElem(LinkList *list, int index){

int i ;

Elem *elem;

// 逐项访问

if ( index > list->size/2 ){

elem = list->last;

for ( i = list->size-1 ; i >= index ; i-- ){

if( i == index ){

return elem;

}

elem = elem->prev;

}

} else {

elem = list->first;

for ( i = 0 ; i <= index ; i++ ){

if( i == index ){

return elem;

}

elem = elem->next;

}

}

}

// 移除元素

void removeIndexL(LinkList *list, int index){

Elem *elem = getElem(list, index);

elem->prev->next = elem->next;

elem->next->prev = elem->prev;

if( index == 0 ){

list->first = elem->next;

}

list->size--;

}

void removeElemL(LinkList *list, Elem *e){

int i;

Elem *elem = list->first;

//    while(e != elem ){

//        elem = elem->next;

//    }

//    elem->prev->next = elem->next;

//    elem->next->prev = elem->prev;

//    if( list->first == elem ){

//        list->first = elem->next;

//    }

int flag = 0;

for ( i = 0 ; i size ; i++ ){

if( elem == e ){

elem->prev->next = elem->next;

elem->next->prev = elem->prev;

if( list->first == elem ){

list->first = elem->next;

}

if( list->last == elem ){

list->last = elem->prev;

}

flag = 1;

}

elem = elem->next;

}

if(!flag) printf("没能完成任务!!!

");

list->size--;

}

/*********************************************************************************

* 链表需要

********************************************************************************/

void init(){

Nodes.size = 0;

Elems.size = 0;

TreeNodes.size = 0;

}

// 新建节点,返回节点指针

Node *createNode(char value,int weight){

Node *p = Nodes.nodes+Nodes.size;

p->value = value;

p->weight = weight;

Nodes.size++;

return p;

}

TreeNode *createTreeNode(Node *node){

TreeNode *p = TreeNodes.nodes+TreeNodes.size;

p->node = node;

p->left = NULL;

p->parent = NULL;

p->right = NULL;

TreeNodes.size++;

return p;

}

Elem *createElem( TreeNode *node ){

Elem *p = Elems.elems+Elems.size;

p->tNode = node;

Elems.size++;

if( Elems.size == 200 ) Elems.size = 0; // 注意不能超过200,否则数据错误

return p;

}

// 返回获取最小节点

Elem *removeMin(LinkList *list){

Elem *elem = list->first;

Elem *p = elem;

int minWeight = p->tNode->node->weight ,w;

//    while( elem->next != list->first ){

//        elem = elem->next;

//        w = elem->tNode->node->weight;

//        if( minWeight > w ){

//            p = elem;

//            minWeight = w;

//        }

//    }

//    removeElemL(list,p);

int i;

for ( i = 0 ; i size ; i++ ){

elem = elem->next;

w = elem->tNode->node->weight;

if(minWeight>w){

p = elem;

minWeight = w;

}

}

removeElemL(list,p);

return p;

}

char path[200] = {'0'}; // 字符串存储路径

void printBaseNodes(TreeNode *tNode, int layer){

// 哈夫曼树是完全二叉树

// 判断有无子节点即判断是否为编码节点

if( tNode->left == NULL ){

path[layer+1] = ' ';

printf("字符:%c --> 路径: %s

",tNode->node->value,path);

}

else {

path[layer+1] = '0';

printBaseNodes(tNode->left,layer+1);

path[layer+1] = '1';

printBaseNodes(tNode->right,layer+1);

}

}

void main(){

init(); //全局变量初始化在这里

int i = 0;

char c,hash[95];

LinkList list;

memset(hash,0,sizeof(hash)); //置零

while((c=getchar())!='

'){

// 最好不要输入空格!!!

hash[c-OFFSET]++;

}

printf("---------------------------------

");

initLinkList(&list); // 初始化链表

for(  i = 0 ; i 

if( !hash[i] ) continue;

printf("字符:%c --> 路径: %d

",i+OFFSET,hash[i]);

Node *node = createNode(i+OFFSET,hash[i]);

TreeNode *tNode = createTreeNode(node);

Elem *elem = createElem(tNode);

addFirst(&list,elem); // 完美

}

// 走到这里已经完成了节点创建了

// 现在要将节点构建成一棵哈夫曼二叉树

printf("---------------------------------

");

if( !list.size ){

printf("非法输入,即将退出程序!

");

exit(1);

}

if( list.size == 1 ){

// 如果小于1的话不需要构建树了

printf("字符:%c --> 编码:%s

",list.first->tNode->node->value,"0");

exit(0);

}

while( list.size > 1 ){

Elem *p1 = removeMin(&list);

printf("最小权值(1)-字符:%c --> 权重:%d

",p1->tNode->node->value,p1->tNode->node->weight);

Elem *p2 = removeMin(&list);

printf("最小权值(2)-字符:%c --> 权重:%d

",p2->tNode->node->value,p2->tNode->node->weight);

Node *p3Node = createNode(0,p1->tNode->node->weight + p2->tNode->node->weight); // 新建一个节点

TreeNode *p3tNode = createTreeNode(p3Node); // 新建一个树节点

Elem *p3 = createElem(p3tNode); // 新建链表元素

p1->tNode->parent = p3->tNode; // 父节点指向p3

p2->tNode->parent = p3->tNode; // 父节点指向p3

p3->tNode->left = p1->tNode; // p1 权重最小,为左节点

p3->tNode->right= p2->tNode; // p2 权重最大,为右节点

// printf("权值:%d + %d --> %d

",p1->tNode->node->weight,p2->tNode->node->weight,p1->tNode->node->weight + p2->tNode->node->weight);

printf("生成权值(3)-字符:%c --> 权重: %d

",p3->tNode->node->value,p3->tNode->node->weight);

addFirst(&list,p3); //  添加到表头可以优先取出(如果权重最小的话)

}

printf("哈夫曼树构建完成 --> 表长:%d

", list.size );

// 如果表长不为 1 , 那么就是有问题了

// 到此已经构建好了哈夫曼树了

// 现在要写路径算法,输出编码

printf("---------------------------------

");

TreeNode *root = list.last->tNode; // 获取根节点,已经不需要链表了

// 测试

printf("根下左右叶 --> 左叶:%d --> 右叶:%d

",root->left->node->weight,root->right->node->weight);

printBaseNodes(root,0);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值