首先小编来介绍一下 Huffman Tree

根据每个结点的权值不同把每个结点放在树的不同层,权值越大,层数越小;

在一个已知的数据中对这组数据进行HuffmanTree 的构建,

1、每次将最小的两个结点取出进行自下而上的顺序构建树,

2、将其权值相加放在数组中,并将这两个结点去除,

3、循环 1、2 步骤,直至只有一个结点,HuffmanTree构建成功

Ps:我这里是默认 从左到右 从小到大的顺序来构建的,顺序无所谓,只是自己在写的时候将构建顺序约定好,方便敲出来

#include<stdio.h>
#include<stdbool.h>
/*
4
9 8 1 5
9 8 1 5 6        9 8 0 0 6			2	3
9 8 0 0 6 14	 9 0 0 0 0 14		1	4
9 0 0 0 0 14 23	 0 0 0 0 0 0  23	0	5

6
9 8 1 5 4 6
*/
typedef struct Node {
	bool flag;		// 用来标记该结点 是否 是有效结点 
	int weight;		// 权值 
	int parent;		// 父节点 
	int leftChild;	// 左孩子 
	int rightChild;	// 右孩子 
}HuffmanTreeNode;

// 初始化 HuffmanTree,将数据放入数组的前 N 个位置 
void initialTree(HuffmanTreeNode [],int,int);
// 打印整个HuffmanTree 数组 
void output(HuffmanTreeNode [],int);
// 输出某一个位置的信息 
void outputOneNode(HuffmanTreeNode);
// 在初始化HuffmanTree的基础上,创建Huffman 
void createHuffmanTree(HuffmanTreeNode [],int,int);
// 挑选有效的HuffmanTree结点中的最小的结点索引 
int  selectMinIndex(HuffmanTreeNode [],int);
// 判断 挑选的两个新的索引 是否是两新的 或是 只有一个是新的 
bool judgeAllNewIndex(int,int,int,int);
// 将结点 聚合成HuffmanTree  
void converge(int,int,int,HuffmanTreeNode []);

int main(void){
	int n;
	scanf("%d",&n);
	HuffmanTreeNode huffmanTree[2*n-1];
	initialTree(huffmanTree,n,2*n-1);
	output(huffmanTree,2*n-1);
	createHuffmanTree(huffmanTree,n,2*n-1);
	output(huffmanTree,2*n-1);
	return 0;
}

void converge(int left,int right,int i,HuffmanTreeNode h[]){
	h[left].parent = i;
	h[left].flag = false;
	h[right].parent = i;
	h[right].flag = false;
	
	h[i].weight = h[left].weight + h[right].weight;
	h[i].leftChild = left;
	h[i].rightChild = right;
}

bool judgeAllNewIndex(int left,int right,int tmpLeft,int tmpRight){
	if(left == tmpLeft){
		return false;
	}
	if(left == tmpRight){
		return false;
	}
	if(right == tmpLeft){
		return false;
	}
	if(right == tmpRight){
		return false;
	}
	return true;
}

int selectMinIndex(HuffmanTreeNode h[],int n){
	int i;
	int index = 0;
	for(i = 0;i < n;i ++){
		if(h[i].flag != false){
			index = i;
			break;
		}
	}
	int min = h[index].weight;
	for(i = index;i < n;i++){
		if(h[i].flag != false){
			if(h[i].weight < min){
				index = i;
				min = h[i].weight;
			}
		}
	}
	h[index].flag = false; // 之前没有写这个,导致每次挑选后索引相同,在下次挑选是这个点应该视为无效结点才对 
	return index;
}

void createHuffmanTree(HuffmanTreeNode h[],int n,int capacity){
	int i;
	int tmpLeft = -1,tmpRight = -1;
	for(i = n;i < capacity;i ++){
		int left = selectMinIndex(h,i);
		int right = selectMinIndex(h,i);
		if(judgeAllNewIndex(left,right,tmpLeft,tmpRight)){
			converge(left,right,i,h);
			tmpLeft = left;
			tmpRight = right;
		}else{
			tmpLeft = left;
			tmpRight = right;
			converge(tmpLeft,tmpRight,i,h);
		}
	}
}

void outputOneNode(HuffmanTreeNode h){
	printf("flag=%d weight=%02d parent=%02d leftChild=%02d rightChild=%02d\n",h.flag,h.weight,h.parent,h.leftChild,h.rightChild);
}

void output(HuffmanTreeNode h[],int n){
	int i;
	for(i = 0;i < n;i ++){
		outputOneNode(h[i]);
	}
	putchar('\n');
}

void initialTree(HuffmanTreeNode h[],int n,int capacity){
	int i;
	for(i = 0;i < n;i ++){
		scanf("%d",&h[i].weight);
		h[i].flag = true;
		h[i].parent = h[i].leftChild = h[i].rightChild = -1;
	}
	for(i = n;i < capacity;i ++){
		h[i].weight = 0;
		h[i].flag = true;
		h[i].parent = h[i].leftChild = h[i].rightChild = -1;
	}
}