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

被折叠的 条评论
为什么被折叠?



