数据结构第十天——N皇后问题,哈夫曼树的编码与解码

一、N皇后问题

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

int place(int *paraSolution, int paraT) {
	int j;
	for (j = 1; j < paraT; j ++) {
		if ((abs(paraT - j) == abs(paraSolution[j] - paraSolution[paraT])) || paraSolution[j] == paraSolution[paraT]) {
			return 0;
		}
	}
	return 1;
}

void backtracking(int *paraSolution, int paraN, int paraT) {
	int i;
	if (paraT > paraN) {
		for (i = 1; i <= paraN; i ++) {
			printf("%d ", paraSolution[i]);
		}
		printf("\n");
	} else {
		for (i = 1; i <= paraN; i ++) {
			paraSolution[paraT] = i;
			
			if (place(paraSolution, paraT) == 1) {
				backtracking(paraSolution, paraN, paraT + 1);
			}
		}
	}
}

void nQueen(int paraN) {
	int i;
	int solution[paraN + 1];
	for (i = 0; i <= paraN; i ++) {
		solution[i] = 0;
	}
	
	backtracking(solution, paraN, 1);
}

int main() {
	nQueen(5);
	
	return 0;
}

结果

1 3 5 2 4
1 4 2 5 3
2 4 1 3 5
2 5 3 1 4
3 1 4 2 5
3 5 2 4 1
4 1 3 5 2
4 2 5 3 1
5 2 4 1 3
5 3 1 4 2

注意:

(1)abs取绝对值,用来判断是否同一对角线上

(2)重点中的重点,back回溯函数,当满足一种情况时,就继续判断下去,不满足就回到上一个结点,十分便捷!!!

二、哈夫曼树的编码与解码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct HuffmanTree {
	int weight;
	int parent;
	int LChild;
	int RChild;
} HTNode, *HuffmanTreePtr;

void Select(HuffmanTreePtr tempPtr, int Length, int *LChild, int *RChild) {
	int i, min1 = 99999, min2 = 99999;
	*LChild = 0;
	*RChild = 0;
	
	for (i = 1; i <= Length; i ++) {
		if (tempPtr[i].parent == 0) {
			if (tempPtr[i].weight < min1) {
				min2 = min1;
				*RChild = *LChild;
				min1 = tempPtr[i].weight;
				*LChild = i;
			} else if (tempPtr[i].weight < min2) {
				min2 = tempPtr[i].weight;
				*RChild = i;
			}
		}
	}
}

HuffmanTreePtr InitHuffmanTree(int weight[], int Length) {
	HuffmanTreePtr tempPtr = (HuffmanTreePtr)malloc(sizeof(HTNode));
	int i, j;
	
	for (i = 1; i <= Length; i ++) {
		tempPtr[i].weight = weight[i - 1];
		tempPtr[i].parent = 0;
		tempPtr[i].LChild = 0;
		tempPtr[i].RChild = 0;
	}
	
	j = Length + Length - 1;
	for (; i <= j; i ++) {
		tempPtr[i].weight = 0;
		tempPtr[i].parent = 0;
		tempPtr[i].LChild = 0;
		tempPtr[i].RChild = 0;
	}
	
	int LChild, RChild;
	for (i = Length + 1; i <= j; i ++) {
		Select(tempPtr, i - 1, &LChild, &RChild);
		tempPtr[i].weight = tempPtr[LChild].weight + tempPtr[RChild].weight;
		tempPtr[LChild].parent = i;
		tempPtr[RChild].parent = i;
		tempPtr[i].LChild = LChild;
		tempPtr[i].RChild = RChild;
	}
	
	return tempPtr;
}

void HuffmanTreeEncoding(HuffmanTreePtr tempPtr, int Length, char str[], char EncodResult[][100]) {
	char code[100];
	int i, codeLength, j, parent, k;
	
	for (i = 1; i <= Length; i ++) {
		codeLength = Length - 1;
		int row = 1;
		j = i;
		parent = tempPtr[i].parent;
		
		while (parent != 0) {
			codeLength --;
			if (tempPtr[parent].LChild == j) {
				code[codeLength] = '0';
			} else {
				code[codeLength] = '1';
			}
			j = parent;
			parent = tempPtr[parent].parent;
		}
		
		printf("%c的编码:", str[i - 1]);
		
		EncodResult[i - 1][0] = str[i - 1];
		for (k = 0; k < Length; k ++) {
			if (code[k] == '0' || code[k] == '1') {
				printf("%c", code[k]);
				EncodResult[i - 1][row] = code[k];
				row ++;
			}
		}
		EncodResult[i - 1][row] = '\0';
		printf("\n");
		memset(&code, -1, Length);
	}
}

void decodeHuffmanTree(char decode[], int length, char str[], char EncodResult[][100], int encodelength) {
	int i, j, k;
	
	for (i = 0; i < length; i ++) {
		for (j = 0; j < encodelength; j ++) {
			if (decode[i] == EncodResult[j][0]) {
				k = 1;
				for (; EncodResult[j][k] != '\0'; k ++) {
					printf("%c", EncodResult[j][k]);
				}
				break;
			}
		}
	}
	
	printf("\n");
}

int calculateWeights(char decode[], int weight[], char str[], int length) {
	int i, j;
	int strlength = 1;
	
	str[0] = decode[0];
	weight[0] ++;
	for (i = 1; i < length; i ++) {
		for (j = 0; j < strlength; j ++) {
			if (decode[i] == str[j]) {
				weight[j] ++;
				break;
			}
		}
		if (j >= strlength) {
			str[strlength] = decode[i];
			weight[strlength] ++;
			strlength++;
		}
	}
	
	return strlength;
}

int findtree(HuffmanTreePtr tempPtr, char code, int location) {
	if (code == '1') {
		return tempPtr[location].RChild;
	} else {
		return tempPtr[location].LChild;
	}
}

void DecodeString(HuffmanTreePtr tempPtr, char encode[], int encodelength, int treelength, char str[]) {
	int i, j;
	char theend[100];
	int printlength = 0;
	
	for (i = 0; i < encodelength; i ++) {
		j = i;
		int location = treelength;
		while (tempPtr[location].LChild != 0) {
			location = findtree(tempPtr, encode[j], location);
			j ++;
		}
		i = j - 1;
		if (j > encodelength) {
			printf("Error,输入有误,无法解码");
			return;
		}
		theend[printlength] = str[location - 1];
		printlength ++;
	}
	
	printf("解码结果是:"); 
	for (i = 0; i < printlength; i ++) {
		printf("%c", theend[i]);
	}
}

int main() {
	int i, j;
	int weight[100], strlength;
	char decode[100], str[100];
	int length;
	HuffmanTreePtr tempPtr;
	char EncodResult[100][100];
	char encode[100];
	int encodelength;
	
	printf("请输入要解码的串:");
	gets(decode);
	length = strlen(decode);
	
	for (i = 0; i < length; i ++) {
		weight[i] = 0;
	}
	
	strlength = calculateWeights(decode, weight, str, length);
	
	tempPtr = InitHuffmanTree(weight, strlength);
	printf("哈夫曼树各结点值:\n");
	
	for (j = 1; j <= strlength * 2 - 1; j ++) {
		printf("%d ", tempPtr[j].weight);
	}
	printf("\n");
	
	HuffmanTreeEncoding(tempPtr, strlength, str, EncodResult);
	
	printf("编码结果:\n");
	decodeHuffmanTree(decode, length, str, EncodResult, strlength);
	
	printf("输入想解码的串:\n");
	gets(encode);
	encodelength = strlen(encode);
	
	DecodeString(tempPtr, encode, encodelength, strlength * 2 - 1, str);
	
	return 0;
}

其中一个输入结果

请输入要解码的串:ccseatrews
哈夫曼树各结点值:
2 2 2 1 1 1 1 2 2 4 4 6 10
c的编码:110
s的编码:111
e的编码:00
a的编码:010
t的编码:011
r的编码:100
w的编码:101
编码结果:
1101101110001001110000101111
输入想解码的串:
1101110001001110110000
解码结果是:cseatwre

总结与说明

读入一个字符串,统计每个字符出现的频率,然后构建哈夫曼树,算出每个字符的编码

读入一个新的01字符串,将其解码为字符,重点是构建树时,用数组的形势去理解

编码是,是从叶到根,倒叙的方式实现每个字符的编码

解码我的思路是,从根节点开始,读入1就前往右儿子结点,0就前往左儿子结点,直到没有下一个结点为止,再确定数组下标,对应字符数组,转换成字母

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值