哈夫曼树(c语言)

哈夫曼树(霍夫曼树)又称为最优树.
1、路径和路径长度
在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。
2、结点的权及带权路径长度

哈夫曼树(3)

若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。
3、树的带权路径长度
树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL。


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

#define TYPE htNode *

#define MAX_SZ 256

//队列树节点
typedef struct _htNode
{
	char symbol;
	struct _htNode* left;
	struct _htNode *right;
	
} htNode;

//树根
typedef struct _htTree
{
	htNode* root; 

} htTree;

//树节点
typedef struct _hlNode
{
	char symbol;   //索引字符  'a'
	char* code;    //编码 010101
	struct _hlNode* next;  //下一个

}hlNode;

typedef struct _hlTable
{
	hlNode* first; //指向第一个
	hlNode* last;  //指向下面的每一个

} hlTable;

//队列节点
typedef struct _pQueueNode
{
	TYPE val;	
	unsigned int priority;
	struct _pQueueNode* next;
}pQueueNode;

//
typedef struct _pQueue
{
	unsigned int size;   //队列的长度;当队列剩下一个元素时就是一个哈夫曼树
	pQueueNode * first;
}pQueue;


//初始化队列
void initPQueue(pQueue** queue)
{
	(*queue) = (pQueue*)malloc(sizeof(pQueue));
	(*queue)->first = NULL;
	(*queue)->size =  0 ;

}


//填充队列
void addPQueue(pQueue** queue, TYPE val, unsigned priority)
{
	if ((*queue)->size == MAX_SZ)
	{
		printf("\n Queue is full\n");
		return;
	}

	pQueueNode * aux = (pQueueNode*)malloc(sizeof(pQueueNode));
	aux->priority = priority;
	aux->val = val;

	if ((*queue)->size == 0 || (*queue)->first == NULL)
	{
		//空队列
		aux->next = NULL;
		(*queue)->first = aux;
		(*queue)->size++;
	}
	else
	{
		if (priority <= (*queue)->first->priority)
		{
			aux->next = (*queue)->first;
			(*queue)->first = aux;
			(*queue)->size++;
		}
		else
		{
			pQueueNode* iterater = (*queue)->first;

			//迭代器
			while (iterater->next != NULL)
			{
				if (priority <= iterater->next ->priority)
				{
					aux->next = iterater->next;
					iterater->next = aux;
					(*queue)->size++;
					return;
				}
				//一直寻找更小的节点
				iterater = iterater->next;
			}

			//超过最大的
			if (iterater->next == NULL)
			{
				aux->next = NULL;
				iterater->next = aux;
				(*queue)->size++;
				return;
			}

		}
	}
}

//获取树节点
TYPE getPQueue(pQueue** queue)
{
	TYPE returnValue = NULL;
	if ((*queue)->size > 0)
	{
		returnValue = (*queue)->first->val;
		(*queue)->first = (*queue)->first->next;
		(*queue)->size--;

	}
	else
	{
		printf("\pQueue is empty \n");

	}
	return returnValue;
}
  htTree * builfTree(char *inputString )
  {
	  int* probability = (int*)malloc(sizeof(int) * 256);

	  //初始化
	  for (int i = 0; i < 256; i++)
	  {
		  probability[i] = 0;
	  }
	//统计待编码的字符串各个字符出现的次数
	  for (int j = 0;inputString[j] != '\0'; j++)
	  {
		  //如穿进去的是I  ==73  ==> probability[73]++
		  probability[(unsigned char)inputString[j]]++;

	  }
	  //pQueue队列的头指针
	  pQueue* huffmanQueue;

	  //初始化队列
	  initPQueue(&huffmanQueue);
	  //填充队列
	  for (int k = 0 ; k < 256; k++)
	  {
		  if (probability[k] != 0)
		  {
			  htNode* aux = (htNode*)malloc(sizeof(htNode));
			  aux->left = NULL;
			  aux->right = NULL;
			  aux->symbol = (char)k;

			  addPQueue(&huffmanQueue, aux, probability[k]);
		  }
	  }
	  free(probability);

	  //生成一颗哈夫曼树
	  while (huffmanQueue->size != 1)
	  {
		  //新节点的权
		  int prority = huffmanQueue->first->priority;

		  //两个节点之和
		  prority += huffmanQueue->first->next->priority;

		  htNode* left = getPQueue(&huffmanQueue);
		  htNode* right = getPQueue(&huffmanQueue);

		  htNode* newNode = (htNode*)malloc(sizeof(htNode));
		  newNode->left = left; 
		  newNode->right = right;

		  addPQueue(&huffmanQueue, newNode, prority);
	  }

	  //根节点huffmanQueue->size = 1 时只有一个节点
	  htTree* tree = (htTree*)malloc(sizeof(htTree));
	  tree->root = getPQueue(&huffmanQueue);
	  return tree;
  
	
  }
  void  traverseTree(htNode* treeNode, hlTable** table, int k, char code[256])
  {
	  //叶子
	  if (treeNode->left == NULL && treeNode->right == NULL)
	  {
		  code[k] = '\0';
		  hlNode* aux = (hlNode*)malloc(sizeof(hlNode));
		  int len = strlen(code) + 1;
		  aux->code = (char*)malloc(sizeof(char) * len);
		  
		  //errno_t strcpy_s(char *restrict dest, rsize_t destsz, const char *restrict src);
		   strcpy_s(aux->code,len, code);
		  aux->symbol = treeNode->symbol;
		  aux->next = NULL;

		  if ((*table)->first == NULL)
		  {
			  //只有一个节点first 、last都指向aux
			  (*table)->first = aux;
			  (*table)->last = aux;

		  }
		  else
		  {
			  //已有节点
			  (*table)->last->next = aux;
			  (*table)->last = aux;
		  }
	  }
	  
	  //分支
	  if (treeNode->left != NULL)
	  {
		  code[k] = '0';
		  traverseTree(treeNode->left, table, k + 1, code);

	  }
	  if (treeNode->right != NULL)
	  {
		  code[k] = '1';
		  traverseTree(treeNode->right, table, k + 1, code);

	  }


  }


  hlTable* buildTable(htTree* huffmanTree)
  {
	  hlTable *table = (hlTable*)malloc(sizeof(hlTable));
	  table->first = NULL;
	  table->last = NULL;

	  char code[256];
	  int k = 0;  //往下走一级加一  位于第几层


	  //填充编码
	  traverseTree(huffmanTree->root, &table, k, code);
	  return table;
  }


  void encode(hlTable* table, char* stringToEncode)
  {
	  hlNode* traversal;
	 // printf("Encode......\n\nInput string:\n%s\n\nEncode string:\n", stringToEncode);
	  printf("Encode......\n\nInput string:\n%s\n\nEncode string:\n", stringToEncode);
	  for (int i = 0;stringToEncode[i] != '\0'; i++)
	  {
		  traversal = table->first;
		  while (traversal->symbol != stringToEncode[i]) //地址异常
		  {
			  traversal = traversal->next;
		  }
		  printf("%s\t", traversal->code);
	  }
	  printf("\n");
  }
  void decode(htTree* tree, char* stringToDecode)
  {
	 htNode* traversal = tree->root;
	 printf("\n\n");
	 printf("Encode......\n\n输入的编码:\n%s\n\n解码后:\n", stringToDecode);
	 for (int i = 0; stringToDecode != '\0'; i++)
	 {
		if (traversal->left == NULL && traversal->right == NULL)
		{
			printf("%c", traversal->symbol);
			traversal = tree->root;
		}
		if (stringToDecode[i] == '0')
		{
			traversal = traversal->left;
		}
		if (stringToDecode[i] == '1')
		{
			traversal = traversal->right;
		}
		if (stringToDecode[i] != '0' && stringToDecode[i] != '1')
		{
			//printf("\nThe input string is not coded correctle!\n");
			printf("\n\n");
			return;
		}
	 }
	 if (traversal->left == NULL && traversal->right == NULL)
	 {
		printf("NULL");
	 }
  }
  int main()
  {
	  char str[100] = "这是一个哈夫曼树 huffmanTree ,Very well done !!";
	  char str2[400] = "1100101111011110111000011001111011011010011111111011111100011010111110011000111100111101111110100101111101000000100011011101011010011010111001001101110001010010110011001010101010010101101100000000100101100101001001101110001000100";
	  htTree* codeTree = builfTree(str);
	  hlTable* codeTable = buildTable(codeTree);
	  encode(codeTable,str);
	  decode(codeTree,str2 );

	  return 0;
  }


  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值