哈夫曼编码和解码

哈夫曼编码和解码, 内部代码纯手工实现 

// hufuman3.cpp.cpp : 定义控制台应用程序的入口点。内部代码纯手工实现
#include <iostream>
#include<stdlib.h>
#include<string.h>

using namespace std;
typedef struct huTreeNode
{
	char a;
  struct huTreeNode * rchild;
  struct huTreeNode * lchild;
}NODE,*TYPE;

typedef struct QueueNode{
	struct huTreeNode * val;
	int probabliy;
	struct QueueNode * next;
}QUEUENODE, *pQUEUENODE;
typedef struct QUEUE{
   int size;
   pQUEUENODE pHead;
}*pQUEUE;

typedef struct hlTable{
char symbol;
char * code;
struct hlTable * pNext;
}HLTABLE,* pHLTABLE;
//队列头指针
struct QUEUE * pQ=(struct QUEUE *)malloc(sizeof(struct QUEUE));
//table 头指针
   pHLTABLE pTHead=(pHLTABLE)malloc(sizeof(HLTABLE));
   pHLTABLE pTable=pTHead;

void initQueue(pQUEUE pQ)
{
//	pQ=(struct QUEUE *)malloc(sizeof(struct QUEUE));
	pQ->size=0;
//	pQUEUENODE head=(pQUEUENODE)malloc(sizeof(QUEUENODE));
	pQ->pHead=(pQUEUENODE)malloc(sizeof(QUEUENODE));
	pQ->pHead->next=NULL;
	return ;
}

 void creatQueue(pQUEUE pQ,char inputString,int *probabliy)
{
	
	pQUEUENODE pQueueNode=(pQUEUENODE)malloc(sizeof(QUEUENODE));
	pQueueNode->next=NULL;
	TYPE node=(TYPE)malloc(sizeof(struct huTreeNode));
	node->a =inputString;
	node->rchild=NULL;
	node->lchild=NULL;
	pQueueNode->val=node;
	pQueueNode->probabliy=probabliy[(int)inputString];	
	if(pQ->pHead->next==NULL)
	{
	  pQ->pHead->next=pQueueNode;
    pQ->pHead->next->next =NULL;
	}
	else
	{
		//找重复 去重复
		pQUEUENODE p=pQ->pHead;
		while(p->next!=NULL)
		{
			if(p->next->val->a==inputString)
			{
             return ;
			}
			p=p->next;
		}

		//入队列
	 p=pQ->pHead;
		while(1)
		{
			if(p->next !=NULL &&  pQueueNode->probabliy>p->next->probabliy)
			{
				  p=p->next;
			}
			else
			{
			pQueueNode->next=p->next;
				p->next=pQueueNode;
				break;
			}
		}
	}
	 pQ->size++;
	 //pQ->pHead=pQueueNode;
	// printf("%c\n",pQ->pHead ->val->a);
	return ;
}

pQUEUENODE outQueue(pQUEUE pQ)
{
	if(pQ->size==0)
	{
		printf("队列已空 出队失败");
		return NULL;
	}
	else
	{
	pQUEUENODE p=pQ->pHead->next;
	pQ->pHead->next=pQ->pHead->next->next;
	pQ->size--;
	return p;
	}
}

void inQueue(pQUEUE pQ, pQUEUENODE pQueueNode)
{
	pQUEUENODE p;
	 p=pQ->pHead;
		while(1)
		{
			if(p->next !=NULL &&  pQueueNode->probabliy>p->next->probabliy)
			{
				  p=p->next;
			}
			else
			{
			pQueueNode->next=p->next;
				p->next=pQueueNode;
				break;
			}
		}
	pQ->size++;
	return ;
}

TYPE buildTree(char * inputString)
{
	int i=0;
	char m;
	int *probabliy=(int *)malloc(sizeof(int)*256);
	for(i=0;i<256;i++)
	{
		probabliy[i]=0;
	}
	i=0;
	while(inputString[i]!='\0')
	{
		probabliy[(int)inputString[i]]++;
		i++;
	}
	
	initQueue(pQ);
	
    i=0;
	while(inputString[i]!='\0')
	{
    m=inputString[i];
	creatQueue(pQ,m,probabliy);
	i++;
	}
	//开始建树
	while(pQ->size>=2)
	{
		pQUEUENODE p1=(pQUEUENODE)malloc(sizeof(QUEUENODE));
		
	    TYPE node=(TYPE)malloc(sizeof(NODE));
		// huTreeNode * node1=(huTreeNode *)malloc(sizeof(huTreeNode));
		// huTreeNode * node2=(huTreeNode *)malloc(sizeof(huTreeNode));
		node->rchild =NULL;
		node->lchild =NULL;
		node->a ='0';
        p1->val=node;
	    pQUEUENODE p=outQueue(pQ);
	    pQUEUENODE q=outQueue(pQ);
	
	  //node->rchild=node1;
    	p1->val->rchild=q->val;
    	p1->val->lchild=p->val;
	    p1->probabliy=p->probabliy+q->probabliy;
	   //creatQueue(pQ, inputString,probabliy)
		inQueue(pQ,p1);
	
    }
	TYPE  huboot=outQueue(pQ)->val;
	return huboot;
	
}

//遍历
void traversal(TYPE T,pHLTABLE * p,int k,char code[256])
{
	if(T!=NULL)
	{
	
		if(T->rchild==NULL&&T->lchild==NULL)
		{
			code[k]='\0';
			pHLTABLE q=(pHLTABLE)malloc(sizeof(HLTABLE));
			q->symbol=T->a;
			q->code=(char *)malloc(sizeof(char)*(strlen(code)+1));
			strcpy(q->code,code);
			q->pNext=NULL;
			(*p)->pNext=q;
			(*p)=(*p)->pNext;	
		}
		else
		{
			if(T->rchild!=NULL)
			{
				code[k]='0';
				traversal(T->rchild,p,k+1,code);
			}
			if(T->lchild!=NULL)
			{
				code[k]='1';
				traversal(T->lchild,p,k+1,code);
			}
			
		}
		
		
	}
	else
	{
		printf("table 为空");
		return ;
	}
	return;	
}
//建table
void buildTable(TYPE L,pHLTABLE * pTHead)
{
	char code[256];
	pHLTABLE * p;
traversal(L,pTHead,0,code);
	
	return;
}
//enCode定义
void enCode(char * inputString)
{
	 pHLTABLE p;
	 p=pTHead->pNext;
     int i=0,j=0;
	 for(i=0;inputString[i]!='\0';i++)
	 {
		while(p!=NULL)
		 {
			
				if(p->symbol==inputString[i])
				{
					//printf("%c\n",inputString[i]);
					printf("%s",p->code);
					break;
				}
				else
				{
					p=p->pNext;
					if(p==NULL)
					 {
					   printf("存在陌生字符!\n");
					   return ;
					 }
				}
		 }	 
		p=pTHead->pNext;
	 }
	 printf("\n");
	return ;
}
//decode定义
void deCode(char * inputString)
{
	 int t=strlen(inputString);
	// printf("%d\n",t);
	char str[200];
	 pHLTABLE p;
	 p=pTHead->pNext;
     int i=0,j=0;

		while(inputString[i]!='\0')
		 { 
			   str[j]=inputString[i];
			   j++; 
			   i++;
			   str[j]='\0';
			   while(p!=NULL)
			   {
					if(strcmp(p->code,str)==0)
					{
					//  printf("ppppp%s\n",str);
						printf("%c",p->symbol);
						j=0;
					  //  j--;
						break; 
					}
					else
					{
						p=p->pNext;
					}
              
				   if(p==NULL)
						 {
							 break;
						 }
			   }
			  p=pTHead->pNext;
		 }	
	 printf("\n");
	return ;
}


//主函数
int main()
{
	//table链表头指针	
	pTHead->pNext =NULL;
	//参考数据源 
	TYPE L=buildTree("abab12340ljiuof56jyrkwe4uii kyerqqw  o...,,ddeeeeeuhd%%%*khfuikj,yrkwesdfret567563tyryeydwrtddiiingfryui54874buyiy iu 98\ uyiiy uy7igi09.,;'[]");
    buildTable(L,&pTable);
    cout<<"编码之后为:" <<endl; 
	enCode("khfuikj,yrkwesdfdddffousdfdfshjguky");
	cout<<"解码后内容为"<<endl; 
	deCode("0101010111101110010011001010001011100100001111001010011000011100001000000011100000000000000000111001110101001010010000100000001110000000111010000101011110010111011000100010100001");
	scanf("%d");//防闪退 
	return 0;
}




 

### 关于哈夫曼编码解码的Matlab实现 #### 创建频率表并构建霍夫曼树 为了创建霍夫曼编码,首先需要统计输入数据中各个字符出现的概率,并以此为基础建立一棵二叉树。这棵树由节点组成,其中叶节点代表原始字符及其概率,而非叶子结点则表示两个子节点合并后的累积概率。 ```matlab function [huffTree, huffCodes] = createHuffmanTree(symbols, probabilities) % 构建霍夫曼树... end ``` #### 编写霍夫曼编码器 一旦有了霍夫曼树,就可以通过遍历该树来为每个符号分配唯一的前缀码字。此过程通常涉及深度优先搜索算法,在访问到每一个终端节点时记录路径上的分支方向作为对应的编码字符串[^1]。 ```matlab function encodedData = encodeWithHuffman(tree, inputString) % 对给定字符串进行霍夫曼编码... end ``` #### 设计霍夫曼解码器 对于解码操作来说,只需要按照接收到的比特流沿着霍夫曼树向下寻找匹配项即可。每当找到一个完整的编码序列对应某个特定字符,则将其加入最终输出的结果集中继续处理剩余部分直到全部完成为止[^2]。 ```matlab function decodedText = decodeWithHuffman(encodedBits, tree) % 使用霍夫曼树对位串执行解码... end ``` #### 完整实例演示 下面给出了一组简单的例子说明如何利用上述函数来进行实际的数据压缩与恢复工作: ```matlab % 测试用例:简单英文短句 testStr = 'this is an example of a huffman tree'; % 计算各字母频次分布情况 [symSet, probVec] = calcSymbolProbabilities(testStr); % 初始化霍夫曼编/解码环境 [hufTree, codeTable] = createHuffmanTree(symSet, probVec); disp('生成的霍夫曼编码:'); disp(codeTable); % 进行编码转换 encodedResult = encodeWithHuffman(hufTree, testStr); fprintf('\n原文:\n%s\n', testStr); fprintf('经过霍夫曼编码后得到的二进制形式:\n'); disp(num2str(encodedResult)); % 尝试还原原信息内容 recoveredMsg = decodeWithHuffman(encodedResult, hufTree); fprintf('\n尝试解码...\n'); if strcmp(recoveredMsg,testStr) disp('成功!'); else error(['失败! 原始消息:', testStr,'; 解码结果:', recoveredMsg]); end ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值