哈夫曼编码

双向树的建立实现哈夫曼的编码:


#include <bits/stdc++.h>
using namespace std;

struct betalist {
	int quan;
	char tu;
};

struct haffman {

	int quan;

	struct betalist* ncp = NULL;

	struct haffman* left = NULL;
	struct haffman* right = NULL;
	struct haffman* father = NULL;
};

//struct betalist* head = NULL;
struct haffman*  head = NULL;
struct betalist* P;

int cmp(struct betalist A,struct betalist B) {

	return A.quan < B.quan;
}

struct haffman* add(struct betalist* A) {

	if (head == NULL) {
		head = new struct haffman;
		head->ncp = A;
		head->quan = 1; //
		return head;
	}
	else {
		struct haffman* tmp1 = new struct haffman;
		struct haffman* tmp2 = new struct haffman;
		tmp1->ncp = A;
		tmp1->quan = 0; // 
		tmp2->left = tmp1;
		tmp2->right = head;
		tmp2->quan = 1; //
		head->father = tmp2;
		tmp1->father = tmp2;
		return head = tmp2;
	}
}

void newhuffman() { // 

	int zf;
	char stmp[100];
	if (head != NULL) {
		printf("哈夫曼树已经建立\n");
		return;
	}
	printf("需要建立的字符个数:");
	scanf("%d", &zf);
	getchar();
	P = new struct betalist[zf];
	printf("请以字符串的方式输入字符:");
	for (char s, *q = stmp; s = getchar(), s != '\n'; q++) {
		*q = s;
		*(q + 1) = 0;
	}
	for (int i = 0; i < zf; i++)
		P[i].tu = stmp[i];
	printf("请输入%d个字符的权值(空格间隔):",zf);
	for (int i = 0; i < zf; i++) {
		scanf("%d", &P[i].quan);
	}
	sort(P, P + zf, cmp); // 排序 将权值小的排在前面 ->  权值大的排在后面
	for (int i = 0; i < zf; i++)  // 建树开始 
		add(&P[i]); // 加边
}



void deletehuffman(struct haffman *S) {
	if (P != NULL)
		free(P);
	if (S == NULL)
		return;
	deletehuffman(S->left);
	deletehuffman(S->right);
	free(S);
}
struct haffman* Ktmp;
void finds(char T,struct haffman* h = head) {
	if (h == NULL)
		return;
	if ((h->ncp) != NULL && h->ncp->tu == T) {
		Ktmp = h;
		return;
	}
	finds(T, h->left);
	finds(T,h->right);
}

void HuffmanNO_(char st) {  // 编码可能要 01 背包求解

	finds(st);
	if (!Ktmp) {
		printf("字符%c不存在无法进行编码", st);
	}

	stack<int>STE;

	for (struct haffman* i = Ktmp; i != head; i = i->father) {
		STE.push(i->quan);
	}

	for (; STE.size(); STE.pop())
		printf("%d",STE.top());
	
}
void Huffmansolve(char ns[]) {

	int* zh = new int[strlen(ns)];
	for (int i = 0, j = strlen(ns); i < j; i++)
		zh[i] = ns[i] - '0';
	int tn = 0;
	int pd = 0;
	struct haffman* i;
	if (head == NULL) {
		printf("哈夫曼编码还未建立 无法解密\n");
		return;
	}
	for (i = head;i!=NULL&&tn<strlen(ns);) { // 没有遍历完树
		
		if (zh[tn] == 0) {
			if (i->left) {
				i = i->left;
				tn++;
				pd = 1;
			}
			else  {
				if(i->ncp)
					printf("%c", i->ncp->tu);
				i = head;
				pd = 0;
			}
		}
		else if (zh[tn] == 1) {
			if (i->right) {
				i = i->right;
				tn++;
				pd = 1;
			}
			else {
				if (i->ncp)
					printf("%c", i->ncp->tu);
				i = head;
				pd = 0;
			}
		}
	}
	if (tn >= strlen(ns) && pd && i->ncp) {
		printf("%c", i->ncp->tu);
	}
	else {
		printf("哈夫曼编码有问题");
	}
}

void solve() {

	int x;
	char st[900];
	printf("哈夫曼树编码程序\n");
	printf("作者:吴祖颂\n");

	
	while (1) {
		printf("1->构造哈夫曼编码  2->加密  3->解密哈夫曼编码  4->结束:");
		scanf("%d", &x);
		if (x == 1) {
			newhuffman();
		}
		else if (x == 2) {
			if (head == NULL) {
				printf("Huffman树没有建立,无法编码");
			}
			else {
				printf("输入待加密的单词或字母:");
				cin >> st;
				for (int i = 0, j = strlen(st); i < j; i++)
					HuffmanNO_(st[i]);
			}
			printf("\n");
		}
		else if (x == 3) {
			printf("请输入待解密的哈夫曼编码:");
			cin >> st;
			Huffmansolve(st);
			printf("\n");
		}
		else if (x == 4)
			break;
	}

}


int main() {

	solve();
	system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值