案例讲解-哈夫曼编码的使用

下面模拟对原文本进行编码,然后传输后,进行相应的解析得到原有的数据,真个过程也可以看作是一个典型的压缩、解压缩操作,具体演示代码如下:

#include 

typedef struct INPUT
{
	unsigned char * data;
	int len;
}INPUT;

void test(INPUT test, char code[][21]);

void main()
{
	freopen("input.txt", "r", stdin);
	char code[53][21] = { 0 };   //数据的编码0-52
	char text[5][50] = { 0 };    //本来的文本内容
	int value[5][50] = { 0 };    //转化后的数据值
	for (int i = 0; i < 53; i++)
	{
		int temp = 0;
		scanf("%s %d\n", &code[i], &temp);
	}
	for (int i = 0; i < 5; i++)
	{
		int temp = 0;
		gets(text[i]);
	}

	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 50; j++)
		{
			if (text[i][j] == ' ')
			{
				value[i][j] = 0;
			}
			else if (text[i][j] == 0)
			{
				value[i][j] = 0;
			}
			else
			{
				value[i][j] = text[i][j] - 'a' + 1;
			}
		}
	}

	int diff[5][50] = { 0 };          //diff变换得到的值,为传输创造条件
	for (int j = 0; j < 50; j++)diff[0][j] = value[0][j];
	for (int i = 1; i < 5; i++)
	{
		for (int j = 0; j < 50; j++)
		{
			diff[i][j] = value[i][j] - value[i - 1][j] + 26;
		}
	}

	int data[10000] = { 0 };
	int len = 0;
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 50; j++)
		{
			for (int k = 0; k < 21; k++)
			{
				char temp = code[diff[i][j]][k];
				if (temp == 0)break;
				data[len++] = temp - '0';//将diff转换成编码的位,但是占用的是int
			}
		}
	}



	unsigned char finalData[10000] = { 0 };
	int flen = 0;
	for (int i = 0; i < len / 8 + 1; i++)
	{
		finalData[flen++] = (data[i * 8 + 0] << 7) + (data[i * 8 + 1] << 6) + (data[i * 8 + 2] << 5) + (data[i * 8 + 3] << 4)
			+ (data[i * 8 + 4] << 3) + (data[i * 8 + 5] << 2) + (data[i * 8 + 6] << 1) + (data[i * 8 + 7] << 0);
	}

	INPUT inputData = { 0 };
	inputData.len = flen;
	inputData.data = finalData;
	test(inputData, code);
}


typedef  struct  Tree
{
	int left;
	int right;
	int data;
}Tree;
Tree   Node[1000] = { 0 };   //默认表示没有左右子节点及数据值
int    pNodeUse;            //默认有了一个父节点,并且没有数据在里面
int    info[10000] = { 0 };
int    g_info_len = 0;
int    diff[5 * 50];
int    g_diff_len = 0;
int    diff_array[5][50];
int    source_value[5][50];
char   source_text[5][50];

void   init();
void   creatHuffTree(char code[][21]);
void   recoverData(INPUT input);
void   decodeHuff();
void   transDiffArray();
void   decodeDiff();
void   decodeValue();
void   show();


void test(INPUT test, char code[][21])
{
	creatHuffTree(code);
	recoverData(test);
	decodeHuff();
	transDiffArray();
	decodeDiff();
	decodeValue();
	show();
}

void init()
{
	for (int i = 0; i < 1000; i++)
	{
		Node[i].left = Node[i].right = Node[i].data = -1;
	}
	pNodeUse = 1;
}
void   creatHuffTree(char code[][21])
{
	init();

	for (int i = 0; i < 53; i++)
	{
		int currentParent = 0;    //记录父亲节点,不断移动计算
		int j;
		for (j = 0; j < 21; j++)
		{
			if (code[i][j] == '0')//左子点
			{
				if (Node[currentParent].left == -1)
				{
					Node[currentParent].left = pNodeUse;
					currentParent = pNodeUse;
					pNodeUse++;
				}
				else
				{
					currentParent = Node[currentParent].left;
				}

			}
			else if (code[i][j] == '1')
			{
				if (Node[currentParent].right == -1)
				{
					Node[currentParent].right = pNodeUse;
					currentParent = pNodeUse;
					pNodeUse++;
				}
				else
				{
					currentParent = Node[currentParent].right;
				}
			}
			else
			{
				Node[currentParent].data = i;                     //添加值得操作
				break;
			}

		}
		//额外的添加长度
		if (j == 21)
		{
			Node[currentParent].data = i;
		}
	}

}

void recoverData(INPUT input)
{
	int flen = 0;
	for (int i = 0; i < input.len; i++)
	{
		info[flen++] = (input.data[i] & (1 << 7)) >> 7;
		info[flen++] = (input.data[i] & (1 << 6)) >> 6;
		info[flen++] = (input.data[i] & (1 << 5)) >> 5;
		info[flen++] = (input.data[i] & (1 << 4)) >> 4;
		info[flen++] = (input.data[i] & (1 << 3)) >> 3;
		info[flen++] = (input.data[i] & (1 << 2)) >> 2;
		info[flen++] = (input.data[i] & (1 << 1)) >> 1;
		info[flen++] = (input.data[i] & (1 << 0)) >> 0;
		//记录一个全局变量
	}
	g_info_len = flen;
}

void   decodeHuff()                      
{                                 
	int pCurrentNode = 0;
	for (int i = 0; i < g_info_len; i++)
	{
		if (info[i] == 0)
		{
			pCurrentNode = Node[pCurrentNode].left;
		}
		if (info[i] == 1)
		{
			pCurrentNode = Node[pCurrentNode].right;
		}
		if (Node[pCurrentNode].data != -1) //有值的话记录
		{
			diff[g_diff_len++] = Node[pCurrentNode].data;
			pCurrentNode = 0;
		}


	}
	
}

void   transDiffArray()
{
	int tempLen = 0;
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 50; j++)
		{
			diff_array[i][j] = diff[tempLen++];
		}
	}
}

void   decodeDiff()
{
	for (int j = 0; j < 50; j++)
		source_value[0][j] = diff_array[0][j];
	for (int i = 1; i < 5; i++)
	{
		for (int j = 0; j < 50; j++)
		{
			source_value[i][j] = diff_array[i][j] - 26 + source_value[i - 1][j];
		}
	}

}

void   decodeValue()
{
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 50; j++)
		{
			if (source_value[i][j] == 0)//将空终止字符串按空格打印
			{
				source_text[i][j] = ' ';
			}
			else
			{
				source_text[i][j] = source_value[i][j] + 'a' - 1;
			}
		}
	}

}
void   show()
{
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 50; j++)
		{
			printf("%c", source_text[i][j]);
		}
		printf("\n");
	}
}

其中输入input.txt如下:

111100101 0
1011010111101 1
11011110100011 2
1100110101011101 3
11100110 4
110010101011011 5
10011111111111111111 6
00101011011111011 7
010010101110111 8
0010000110101 9
00011010101111 10
001101010101101 11
0000110101101 12
000010101010 13
00000001 14
000000001 15
010010101111101 16
1001110101011111 17
11001100110011001 18
1110011100011100 19
1111100000111 20
1111111000000000 21
101011100101011001 22
10000000000000001 23
11111100000001 24
111111100000001001 25
1111000101 26
10110100111101 27
110111100100011 28
11001101001011101 29
111000110 30
1100100101011011 31
100111110111111111111 32
001010110011111011 33
0100101011010111 34
00100001010101 35
000110101011011 36
0011010101010101 37
00001100101101 38
0000101010010 39
0000000001 40
00000000001 41
0100101011101101 42
10011101010111101 43
110011001100110001 44
10110011100011100 45
11111000000111 46
11111101000000000 47
1010101100101011001 48
100000000000000001 49
101111100000001 50
1111101100000001001 51
111111111111111111 52
hello everyone in professional code test group
this is a simple case for huffman tree
you will see this text if your code is correct
otherwise you need check your code again
good luck for everyone please do your best

你可能感兴趣的:(数据结构与算法)