Пример #1
0
//使用weigh数组构建一个huffman树
HuffmanTree CreateTree(int* weight, int n)
{
	int total = 2 * n - 1;
	HuffmanTree HT = (HuffmanTree)malloc(total * sizeof(HTNode));
	if (!HT)
	{
		printf("HuffmanTree malloc faild!\n");
		exit(-1);
	}
	int i;

	//HT[0...n-1]存放的是需要编码的n个叶子节点
	//初始情况下父节点和左右子节点都为-1
	for (i = 0; i < n; ++i)
	{
		HT[i].parent = -1;
		HT[i].lchild = -1;
		HT[i].rchild = -1;
		HT[i].weight = *weight;
		weight++;
	}

	//HT[n ... 2n-2]存放的是中间构造的二叉树的节点
	for (; i<total; ++i)
	{
		HT[i].parent = -1;
		HT[i].lchild = -1;
		HT[i].rchild = -1;
		HT[i].weight = -1;
	}

	int min1, min2;
	for (i = n; i < total; ++i)
	{
		SelectMin(HT, i, min1, min2);
		HT[min1].parent = i;
		HT[min2].parent = i;
		HT[i].lchild = min1;
		HT[i].rchild = min2;
		HT[i].weight = HT[min1].weight + HT[min2].weight;
	}

	return HT;
}
void HuffmanCodding(HuffTree &hufftree,HuffCode &huffCode,int* w,int n) {
	//建立哈夫曼树
	int lchild, rchild;
	int start;
	int m = 2 * n - 1;//总结点个数
	int i;
	//初始化n个子节点
	for (i = 1; i <=n; i++)
	{
		hufftree[i].weight = w[i];//权重赋值
		hufftree[i].parent = 0;//无父节点
		hufftree[i].lchild = 0;//无左孩子节点
		hufftree[i].rchild = 0;//无右孩子节点
	}
	//初始化非叶子节点
	for (i = n+1; i <=m; i++)
	{
		hufftree[i].weight = 0;
		hufftree[i].parent = 0;
		hufftree[i].lchild = 0;
		hufftree[i].rchild = 0;
	}
	//使用n+1至m的节点建立哈夫曼树
	for (i = n+1; i <=m; i++)
	{
		//这里从i-1开始,因为父节点也会不断地加入
		SelectMin(hufftree,i-1,lchild);//拿到权重小的左节点下标
		hufftree[lchild].parent = i;
		//printf("lchild = %d-->parent = %d\n",lchild, hufftree[lchild].parent);
		hufftree[i].lchild = lchild;
		SelectMin(hufftree,i-1,rchild);//拿到权重小的右节点下标
		//更新hufftree的各种数值
		hufftree[rchild].parent = i;
		//printf("rchild = %d-->parent = %d\n", rchild, hufftree[rchild].parent);
		hufftree[i].rchild = rchild;
		hufftree[i].weight = hufftree[lchild].weight + hufftree[rchild].weight;
		//printf("parent = %d-->lchild = %d-->rchild  = %d\n", hufftree[rchild].parent,lchild,rchild);
	}
	//逆向保存每个字符的哈夫曼编码
	char *temp;//保存
	
	//对于n个叶子节点
	for ( i = 1; i <=n; i++)
	{
		temp = (char*)malloc(sizeof(char)*n);//暂时性地保存编码,逆向保存
		temp[n - 1] = '\0';//最后保存的结束字符
		int c = i;
		int parentIndex;
		start = n-1;//从结束字符的前一位开始,start指向的是填入的那个空
		parentIndex = hufftree[i].parent;
		while (parentIndex!=0)//判断父节点是否有parent下标,是否为根节点
		{
			//printf("child = %d-->parent = %d\n", c, parentIndex);
			if (hufftree[parentIndex].lchild == c)//说明该子节点是其父节点的左孩子
			{
				temp[--start] = '0';//保存‘0’字符
			}
			if (hufftree[parentIndex].rchild == c)//说明该子节点是其父节点的右孩子
			{
				temp[--start] = '1';
			}
			c = parentIndex;//!!!!坑爹2,这个也要更新
			parentIndex = hufftree[parentIndex].parent;//迭代,更新为目前节点的父节点
		}
		//获取到总的编码后
		int length = n-start;//总长度
		huffCode[i] = (char*)malloc(sizeof(char)*length);
		
		//复制!!注意是从start开始复制
		strcpy(huffCode[i],&temp[start]);
		free(temp);
	}
}