哈夫曼树实现

        哈夫曼编码其实就是一种数据压缩的方法,他会根据数据出现的频率来进行重新编码,减少空间大小,比如一段文章中  字符 ‘A’ 出现的频率非常的多,大家都知道一个字符占用八个字节,这时候我们用 二进制1 来代表 字符 ‘A’,那这段文章中所有的 字符‘A’岂不是缩小八倍吗,这意味着出现八次 ‘A’ 才跟原来一个‘A’占用的空间一样大

        我使用优先队列和二叉树来完成哈夫曼树的实现,

        队列的相关知识我就不将了,如果你按照顺序学习的话,队列应该已经学会了

        huffmanTree.h 代码如下: 

#pragma once
#define MAXSIZE 10

//树节点内容
typedef struct _Bnode {

	char value;            //字符
	int weight;            //权值,根据权值的大小来决定出现的频率 

	_Bnode* lchild;        

	_Bnode* rchild;

	_Bnode* parent;        //这个节点是用来记录两个权值的和

}Bnode;

typedef Bnode* BnodePtr;

//队列节点内容

typedef struct _QNode {
	int priority;

	BnodePtr data;

	_QNode* next;

}QNode;

typedef QNode* QNodePtr;

//队列指针
typedef struct _Queue {

	QNodePtr front;        //队列的头

	QNodePtr rear;         //队列的尾

	int length;
}Queue;

//初始化队列
bool initQueue(Queue* LQ);

//插入队列
bool enterQueue(Queue* LQ, Bnode* node, int priority);

//出队列
bool escapeQueue(Queue* LQ, Bnode*& node);

//判断空
bool isEmpty(Queue* LQ);

//判断满
bool isFull(Queue* LQ);

//清空队列
void destroyQueue(Queue* LQ);

//打印队列信息
void printQueue(Queue* LQ);

//实现哈夫曼树的创建
void huffmanTree(Bnode*& huff, int n);        /*这里用了指针引用,是因为我需要把原来的指针改        
                                              变一下指向的目标,(这里用二级指针也可以)*/

huffmanTree.cpp 实现代码如下:

#include "HuffmanTree.h"
#include <iostream>
using namespace std;

//初始化队列
bool initQueue(Queue* LQ) {
	if (!LQ)return false;
	LQ->front = LQ->rear = NULL;
	LQ->length = 0;
	return true;
}

//插入队列
bool enterQueue(Queue* LQ, Bnode* node, int priority) {
	if (!LQ)return false;
	QNode* qNode = new QNode;
	if (!qNode)return false;
	
	qNode->data = node;
	qNode->next = NULL;
	qNode->priority = priority;

	if (LQ->front == NULL && LQ->rear == NULL) {

		LQ->front = qNode;

		LQ->rear = qNode;

		LQ->length++;

		return true;
	}

//下面这段入队顺序可以不一样,因为是优先队列,他会对优先级进行出队,而不是常规队列
//==================================
	qNode->next = LQ->front;

	LQ->front = qNode;

//==================================
	LQ->length++;

	return true;

}

//出队列
bool escapeQueue(Queue* LQ, Bnode*& node) {

	if (!LQ)return false;

	if (isFull(LQ))return false;

	QNode** pre = NULL, *pre_node = NULL;

	QNode* last = NULL, *tmp = NULL;
	
	pre = &LQ->front;

	last = LQ->front;

	tmp = last->next;

    //在这个循环中一直进行优先级的判断
	while (tmp)
	{
		if (tmp->priority < (*pre)->priority) {

			pre = &last->next;

			pre_node = last;
		}

		last = tmp;            //这里也可以写 last = last->next; 主要功能就是跳到下一个节点
		
        tmp = tmp->next;
	}

	tmp = *pre;

	node = (*pre)->data;

	(*pre) = (*pre)->next;	/*指向后后一个节点,就是删除节点的前一个节点指向了删除节点的后一    
                              个节点*/
	delete tmp;

	LQ->length--;

	//两种出队列特殊的情况

	//只有一个节点,并且出队列了

	if (LQ->length == 0) {

		LQ->rear = NULL;        /*这里没有让front = NULL,是因为如果该队列为空,那么在上边的 
                                  (*pre)中就会把front给改变指向了*/
	}

	//出队节点是最后一个节点
	if (pre_node && pre_node->next == NULL) {

		LQ->rear = pre_node;
	}

	return true;
}

//判断空
bool isEmpty(Queue* LQ) {

	if (LQ->length == 0) {

		return true;
	}

	else {

		return false;

	}
}

//判断满
bool isFull(Queue* LQ) {


	if (LQ->length == MAXSIZE)return true;

	return false;
}

//清空队列
void destroyQueue(Queue* LQ) {

	if (!LQ) {

		cout << "空指针" << endl;

		return;
	}

	while (LQ->front)
	{
		QNode* node = LQ->front;

		LQ->front = LQ->front->next;

		delete node;
	}

	LQ->front = NULL;

	LQ->length = 0;

	LQ->rear = NULL;

}

//打印队列信息
void printQueue(Queue* LQ) {
	if (!LQ)return;
	QNode* tmp = LQ->front;
	while (tmp)
	{
		cout << "-" << tmp->data->value << "-" << " ";
		tmp = tmp->next;
	}
	cout << endl;
}


//实现哈夫曼树的创建
void huffmanTree(Bnode*& huff, int n) {
	Queue* LQ = new Queue;
	initQueue(LQ);

	if (!LQ)return;


	for (int i = 0; i < n; ++i) {
		Bnode* node = new Bnode;

        //这次输入的两个值都会记录到value和weight中
		cout << "请输入第 " << i + 1 << " 个字符和出现的次数:" << endl;

		cin >> node->value;
		cin >> node->weight;

		node->parent = NULL;
		node->lchild = NULL;
		node->rchild = NULL;
		cin.get();            //把回车键接受

		enterQueue(LQ, node,node->weight);
	}
	printQueue(LQ);


    //下面就是哈夫曼的实现

	do
	{
		Bnode* node1;    
		Bnode* node2;

		if (!isEmpty(LQ)) {
			escapeQueue(LQ, node1);
			printf("第一个出队列的数:%c, 优先级: %d\n", node1->value,
				node1->weight);
		}
		else {
			break;
		}

		if (!isEmpty(LQ)) {
			escapeQueue(LQ, node2);
			printf("第二个出队列的数:%c, 优先级: %d\n", node2->value,
				node2->weight);
			Bnode* node3 = new Bnode;
			node3->lchild = node1;
			node3->rchild = node2;
			node1->parent = node3;
			node2->parent = node3;
			node3->value = ' ';
			node3->weight = node1->weight + node2->weight;
			enterQueue(LQ, node3, node3->weight);
		}
		else {
			huff = node1;
			break;
		}


	} while (1);

}

main.cpp 代码如下:

#include <iostream>
#include "HuffmanTree.h"

using namespace std;

void preTree(Bnode* root) {
	if (root == NULL)return;
	cout << root->value << " ";
	preTree(root->lchild);
	preTree(root->rchild);

}

int main()
{
	Bnode* root = new Bnode;
	huffmanTree(root, 7);
	preTree(root);


	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45428525/article/details/121534274