数据结构哈夫曼树&N皇后问题

本文详细介绍了哈夫曼树的构建过程及应用,并通过实例演示了哈夫曼编码的生成方法。此外,还探讨了N皇后问题及其解决算法,包括如何通过回溯算法寻找所有可行解。

一.哈夫曼树

哈夫曼树:给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的大权路径长度达到最小,则该二叉树为哈夫曼树,也被称为最优二叉树。

哈夫曼树的构造过程:

初始状态有n棵只有根节点的树,找出其中权值最小的两棵树,生成他们的父节点,父节点的权值为他们权值之和。重复操作,直到只有一颗树为止。

编码:

编码从最小的子树开始,可以使用栈这种数据结构储存他们的位置编码。

第二种可以使用数组,从数组的最后向前开始存储位置编码。

 

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

typedef struct HTNode{ //单结点信息 
	double weight;
	int parent;
	int Lchild,Rchild;
}*huffmanTree,LHT;

typedef char** huffmanCode;

void Select(huffmanTree &HT,int n,int &m1,int &m2){//找到m1,m2这两个权值最小的树 
	int min,i;
	for(i=1;i<=n;i++){
		if(HT[i].parent==0){
			min=i;
			break;
		}
	}
	for(i=min+1;i<=n;i++){
		if((HT[i].parent==0)&&HT[i].weight<HT[min].weight){
			min=i;
		}
	}
	m1=min;
	for(i=1;i<=n;i++){
		if(HT[i].parent==0&&i!=m1){
			min=i;
			break;
		}
	}
	for(i=min+1;i<=n;i++){
		if((HT[i].parent==0)&&(HT[i].weight<HT[min].weight)&&(i!=m1)){
			min=i;
		}
	}
	m2=min;
}

void cHuffmanTree(huffmanTree &HT,double *w,int n){//创建哈夫曼树 
	int m=2*n-1;
	HT=(huffmanTree)calloc(m+1,sizeof(LHT));
	
	for(int i=1;i<=n;i++){
		HT[i].weight=w[i-1];
	}

	for(int i=n+1;i<=m;i++){
		int m1,m2;
		Select(HT,i-1,m1,m2);
		HT[i].weight=HT[m1].weight+HT[m2].weight;
		HT[i].Lchild=m1;
		HT[i].Rchild=m2;
		HT[m1].parent=i;
		HT[m2].parent=i;
	}
	
	printf("哈夫曼树为:\r\n");
	printf("下标 权值 父结点 左孩子 右孩子\r\n"); 
	for(int i=1;i<=m;i++){
		printf("%d %.2lf %d %d %d\r\n",i,HT[i].weight,HT[i].parent,HT[i].Lchild,HT[i].Rchild);
	}
}

void huffCode(huffmanTree &HT,huffmanCode &HC,int n){
	HC=(huffmanCode)malloc(sizeof(char*)*(n+1));
	char *code=(char*)malloc(sizeof(char)*n);
	code[n-1]='\0';
	
	int i;
	for(i=1;i<=n;i++){// 遍历父节点,直到根结点 
		int start =n-1;//让strat指向n-1的位置,向前存储 
		int p=i;
		while(HT[p].parent!=0){
			start--;
			if(HT[HT[p].parent].Lchild==p){
				code[start]='0';
			}else{
				code[start]='1';
			}
			p=HT[p].parent; 
		} 
		HC[i]=(char*)malloc(sizeof(char)*(n - start));
		strcpy(HC[i], &code[start]);
	}
} 

int main(){
	int n=0;
	printf("请输入数据个数:");
	scanf("%d",&n);
	
	double *w=(double*)malloc(n*sizeof(double));
	printf("请输入数据:");
	for(int i=0;i<n;i++){
		scanf("%lf",&w[i]);
	} 
	
	huffmanTree HT;
	cHuffmanTree(HT,w,n);
	
	huffmanCode HC;
	huffCode(HT, HC, n); //构建哈夫曼编码

	for (int i = 1; i <= n; i++) //打印哈夫曼编码
	{
		printf("数据%.2lf的编码为:%s\n", HT[i].weight, HC[i]);
	}
	free(w);
	return 0;
}


测试代码

请输入数据个数:5
请输入数据:1 2 3 4 5
哈夫曼树为:
下标 权值 父结点 左孩子 右孩子
1 1.00 6 0 0
2 2.00 6 0 0
3 3.00 7 0 0
4 4.00 8 0 0
5 5.00 8 0 0
6 3.00 7 1 2
7 6.00 9 3 6
8 9.00 9 4 5
9 15.00 0 7 8
数据1.00的编码为:010
数据2.00的编码为:011
数据3.00的编码为:00
数据4.00的编码为:10
数据5.00的编码为:11

二.N皇后问题

N皇后问题涉及回溯算法。

说说我对回溯算法的理解,比如说是5皇后问题,其实只需要五重for循环去遍历,第i重循环表示遍历第i行的所符合条件的位置。当下一层的遍历结束时,回到上一重循环继续遍历,再找到适合条件的位置后,再进入下一重的循环。

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

bool place(int *solution,int t){
	int j;
	for(j=1;j<t;j++){
		if((abs(t-j)==abs(solution[t]-solution[j]))||solution[t]==solution[j])
		return false; 
	}
	return true;
} 

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

void nQueen(int paraN){
	int i;
	int* solution = (int*)malloc((paraN + 1) * sizeof(int));
	for (i = 0; i <= paraN; i ++)
		solution[i] = 0;

    backtracking(solution, paraN, 1);
}

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

测试代码

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值