西农数据结构作业_Huffman树和Huffman编码(33.3%版)

 

//别看,测试样例一多就过不了
//先在这放着,啥时候有空再改
//如下按照我的想法没有实现版
//哈哈哈哈哈哈哈哈哈 精神状态良好
#include <iostream>
#include <cstring>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <queue>
using namespace std;
struct TreeNode {
	char zimu;
	int weight;
	int parent;
	int leftchild;
	int  rightchild;
	int hti;
	char  huffcode[1000];
	TreeNode() {};
	TreeNode(int w, char z = '\0', int hti = -1, int p = 0, int l = 0, int r = 0) {
		weight = w;
		zimu = z;
		parent = p;
		leftchild = l;
		rightchild = r;

	}
};
class HuffmanTree {
public:
	HuffmanTree(int num) {
		char temp;
		for (int i = 0; i < num; i++) {
			cin >> temp;
			zimu[temp - 65]++;
		}
	}
	void CreateTree();
	void CreateTreecode();
	void Select(int k, int& s1, int& s2);
	void Print();
private:
	TreeNode* HT;
	int n=0;
	int zimu[26] = { 0 };
	//char** HC;
};
struct cmp
{
	bool operator()(const TreeNode* a, const TreeNode* b)const
	{
		return a->weight > b->weight;
	}
};
priority_queue<TreeNode, vector<TreeNode>, cmp> minHeap;
short comp( const TreeNode& a, const TreeNode& b) {
	return a.weight > b.weight;
}
int main() {
	int num;
	cin >> num;
	HuffmanTree Tree(num);
	Tree.CreateTree();
	Tree.CreateTreecode();
	Tree.Print();
}

void HuffmanTree::CreateTree()
{
	int cnt = 0;
	for (int i = 0; i < 26; i++) {
		if (zimu[i] > 0) {
			cnt++;
		}
	}
	n = cnt;
	//cout << n << endl;
	if (cnt <= 1)
		return;

	int m = 2 * n- 1;
	HT = new TreeNode[m + 1];
	int k = 1;
	for (int i = 1; i < m + 1; i++) {
		HT[i].parent = 0;
		HT[i].leftchild = 0;
		HT[i].rightchild = 0;

	}
	for (int i = 0; i < 26; i++) {
		if (zimu[i] > 0) {
			TreeNode temp(zimu[i],i+65,k);
			HT[k] = temp;
			minHeap.push(temp);
			//cout << HT[k].zimu << " " << HT[k].weight << endl;
				k++;
		}
	}
	
	int s1;
	int s2;
	for (int i = n+1; i <=m; i++) {
		//cout << " i" << i-1 << endl;
		Select(i - 1, s1, s2);
		//cout << s1 << " " << s2 << endl;
		HT[s1].parent = i;
		HT[s2].parent = i;
		HT[i].leftchild = s1;
		HT[i].rightchild = s2;
		HT[i].weight = HT[s1].weight + HT[s2].weight;
		HT[i].hti = i;
		minHeap.push(HT[i]);
	}
	/*
	cout << "字符 权 父母 左 右" << endl;
	for (int i = 1; i <=m; i++) {
		cout << HT[i].zimu << " " << HT[i].weight << " " << HT[i].parent << " " << HT[i].leftchild
			<< " " << HT[i].rightchild << endl;
	}
	*/

}

void HuffmanTree::CreateTreecode()
{
	//HC = new char* [n + 1];
	char* cd = new char[n];
	cd[n - 1] = '\0';
	
	for (int i = 1; i <= n; i++) {
		int start = n - 1;
		int c = i;
		int f = HT[i].parent;
		while (f != 0) {
			start--;
			if (HT[f].leftchild == c)
				cd[start] = '0';
			else
				cd[start] = '1';
			c = f;
			f = HT[f].parent;
		}
		for (int j = 0; j < start; j++) {
			HT[i].huffcode[j] = '\0';
		}
		for (int j = start; j < n - 1; j++) {
			//cout << cd[j];
			HT[i].huffcode[j] = cd[j];
			//cout << HT[i].huffcode[j];
		}
		HT[i].huffcode[n - 1] = '\0';
	}
	//delete cd;

	//for (int i = 1; i < n; i++) {
	//	HT[i].huffcode = HC[i];
	//}
}

void HuffmanTree::Select(int k, int& s1, int& s2)
{
	int fmin=1;
	int smin=1;
	TreeNode min1 = minHeap.top();
	minHeap.pop();
	TreeNode min2 = minHeap.top();
	minHeap.pop();
	s1 = min1.hti;
	s2=min2.hti;
	/*
	int pos1, pos2;
	for (int i = 0; i <= k; i++) {
		if (HT[i].parent == 0) {
			if (HT[i].weight < min1) {
				min2 = min1;
				pos2 = pos1;
				min1 = HT[i].weight;
				pos1 = i;
			}
			else if (HT[i].weight < min2) {
				min2 = HT[i].weight;
				pos2 = i;
			}
		}
	}
	s1 = pos1;
	s2 = pos2;
	*/
	for (int i = 1; i <=k; i++) {
		if (HT[i].parent == 0) {
			fmin = i;
			smin = i;
			//cout <<" f s "<< fmin << " " << smin << endl;
			break;
		}
	}
	
	for (int i = 1; i <= k; i++) {
		int temp;
		int flag = 0;

		if (HT[i].weight < HT[fmin].weight&&HT[i].parent==0) {
				smin = fmin;
				fmin = i;
		}
		else if (HT[i].weight < HT[smin].weight&&HT[i].parent==0) {
				smin = i;
		}
		if (fmin == smin && HT[i].weight == HT[fmin].weight && i != fmin&&HT[i].parent==0) {
			smin = i;
		}
		
	}
	if (fmin == smin) {
		for (int i = 1; i <= k; i++) {
			if (HT[i].parent == 0&&i!=fmin) {
				smin = i;
			}
		}
	}
	s1 = fmin;
	s2 = smin;
	//cout << " s1 s2 " << fmin << " " << smin << endl;

}

void HuffmanTree::Print()
{

	sort(HT+1,HT+n+1,comp);
	for (int i = 1; i <= n; i++) {
		cout << HT[i].zimu << " " << HT[i].weight << " ";
		int j = 0;
		for (int j = 0; j < n - 1; j++) {
			if (HT[i].huffcode[j] != '\0')
				cout << HT[i].huffcode[j];
		}
		cout << endl;
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值