huffman树--静态链表和链表实现(借助优先队列)

静态链表实现:

#include<iostream>
#include<vector>
#include<string> 
using namespace std;

const int maxWeight = 32767;

struct HTNode
{
	char data;
	int weight;
	int parent,lchild,rchild;
};
struct HFTree
{
	vector<HTNode>elem;
	int root;
	int num;   // huffman树外结点个数 
};
void createHFTree(HFTree &HT,string value,vector<int>fr)
{//输入数据value[n]和 相应权值fr[n],构造用三叉链表表示的Huffman树HT 
	int min1,min2;
	HT.elem.resize(value.length()*2-1);			//huffman是一颗正则二叉树,有2*n-1个结点 
	for(int i = 0; i < value.length(); i++)	
	{
		HT.elem[i].data = value[i];
		HT.elem[i].weight = fr[i]; 
	}
	for(int i = 0; i < 2*value.length()-1; i++)		 
	{
		HT.elem[i].parent = HT.elem[i].lchild = HT.elem[i].rchild = -1; 
	}
	int s1,s2;
	for(int i = value.length(); i < 2*value.length() - 1 ; i++)			//循环n-1次,因为还有	 
	{																	//n-1个结点要添加 
		min1 = min2 = maxWeight;
		s1 = s2 = 0;
		for(int k = 0;k < i; k++)
		{
			if(HT.elem[k].parent == -1)
			{
				if(HT.elem[k].weight < min1 )		//最小 
				{
					min2 = min1;
					s2 = s1;
					min1 = HT.elem[k].weight;
					s1 = k;
				}
				else if(HT.elem[k].weight < min2)	//次小 
				{
					min2 = HT.elem[k].weight;
					s2 = k;
				}
			}
			
		}
		HT.elem[s1].parent = HT.elem[s2].parent = i;		
		HT.elem[i].lchild = s1;   HT.elem[i].rchild = s2;
		HT.elem[i].weight = HT.elem[s1].weight + HT.elem[s2].weight; 
	}
	HT.num = value.length();   HT.root = 2*value.length() - 2;	
} 

int main()
{
	string values = "ABCDE";
	vector<int> fr = {7,5,2,4,6};
	HFTree HF;
	createHFTree(HF,values,fr); 
	for(int i = 0; i < HF.elem.size(); i++)
	{
		cout<<HF.elem[i].data<<" parent is "<<HF.elem[i].parent<<" lchild is "<<HF.elem[i].lchild<<" rchild is "<<HF.elem[i].rchild
		<<" weight is "<<HF.elem[i].weight<<endl; 
	} 
	return 0;
} 

在这里插入图片描述

二叉链表实现:

#include<iostream>
#include<vector>
#include<string>
#include<queue>

using namespace std;

struct Node
{
	char data;
	double weight;
	Node *lchild,*rchild;
	Node(char _data,double _weight)
	{
		data = _data;
		weight = _weight;
		lchild = rchild = NULL;
	}
};

class cmp
{
public:
	 bool operator()(const Node *n1,const Node *n2) const
	 {
	 	return n1->weight > n2->weight;
	 }
};

void createHuffmanTree(Node *&root,string values,vector<double>weights)
{
	if(values.length() <= 0) 
	{
		root = NULL;
		return ;
	} 
	priority_queue<Node*,vector<Node*>,cmp> q;		//优先队列
	for(int i = 0; i < values.length(); i++)
	{
		Node *newNode = new Node(values[i],weights[i]);
		q.push(newNode); 
	}
	for(int i = 0; i < values.length() - 1; i++)    //循环n-1次,加n-1个结点 
	{//因为huffman树是正则二叉树(只有度为2和0的结点),所以共2n-个结点,所以再加n-1个结点就够了 
		Node *x = q.top();
		q.pop();
		Node *y = q.top();
		q.pop();
		Node* cur = new Node('#',x->weight + y->weight);
		cur->lchild = x;
		cur->rchild = y;	
		q.push(cur); 
	}
	root = q.top();
} 
void printHuffmanCode(const Node *root,string code) 
{
	if(root->lchild == NULL && root->rchild == NULL)
	{
		cout<<root->data<<": huffman code is "<<code<<endl;
	}
	else
	{
		printHuffmanCode(root->lchild,code+"0");
		printHuffmanCode(root->rchild,code+"1");
	}
}
void printHuffmanTree(Node *root,int k)		//这里是先打印水平打印,先打印的右子树再打左子树
{
	if(root != NULL)
	{
		printHuffmanTree(root->rchild,k+5);
		for(int i = 0; i < k; i++)
		{
			cout<<" ";
		}
		cout<<root->data<<endl;
		printHuffmanTree(root->lchild,k+5);
	}
}
int main()
{
	string values = "abcde";
	vector<double>weights = {0.05,0.20,0.35,0.30,0.10}; 
	Node *root = NULL;
	createHuffmanTree(root,values,weights);
	printHuffmanCode(root,"");
	printHuffmanTree(root,0); 
	return 0; 
}

在这里插入图片描述
(注:huffman编码树的形态不一定是一样的,因为同一层左右子女位置可以交换,这里实现的weight小的在左边,大的在右边。

===========================================================

严版huffman:


typedef struct {
	int weight;
	int parent,lchild,rchild;
}HTNode, *HuffmanCode;

typedef char **HuffmanCode;

void HuffmanCoding(HuffmanTree &HT,int *w,int n)
{
	if(n <= -1) return ;
	int m = 2*n-1;
	HT = (HuffmanCode)malloc((m+1)*sizeof(HTNode));
	int i;
	for(HTNode *p=HT, i = 1; i <= n; i++, p++, w++)
	{
		*p = {*w, 0, 0, 0};
	}
	for( ;i <= m; i++) { *p = {0,0,0,0};}
	for(i = n+1;i <= m; i++)
	{
		select(HT, i-1,s1,s2); //s1, s2为权值最小的俩个关键字的下标
		HT[s1].parent = i; Ht[s2].parent = i;
		HT[i].lchild = s1; HT[i].rchild = s2;
		HT[i].weight = HT[s1].weight + HT[s2].weight;
	} 
} 
void getHuffmanCode(HuffmanTree &HT, HuffmanCode&HC)
{
	HC = (HuffmanCode)malloc((n+1)*sizeof(char*));
	cd = (char*)malloc(n*sizeof(char));
	cd[n-1] = "\0";
	for(int i = 1; i <= n; i++)
	{
		int start = n-1;
		for(int c = i,f = HT[i].parent; f != 0; c = f,f = HT[f].parent)
		{//从叶子到根逆向求编码
			if(HT[f].lchild == c) cd[--start] = '0';
			else cd[--start] = '1';
		}
		HC[i] = (char*)malloc((n-start)*sizeof(char));
		strcpy(HC[i], &cd[start]);
	} 
	free(cd); 
}
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值