hafuman 编码

hafuman 编码
这次写代码基本也是一气呵成 ,当然中间还是调试了才正确运行 ,可以通过北邮OJ 的测试 ,其逻辑和在图书馆写在草稿的逻辑没有多大改动,看来写代码之前
做初步分析还是很重要的 , 
http://acm.scs.bupt.cn/onlinejudge/showproblem.php?problem_id=1817 
# include<stdio.h>
# include<stdlib.h>
# include<string.h>

const int N = 2*1000+ 3 ;

# define GetMax(a,b) ((a)>(b) ?(a) :(b) )
struct TreeNode
{
	int data;
	int left,right,father;
	int deep;
};

struct TreeNode ArrayTree[N];
int used[N];

int cmp(const void * a,const void * b)
{
	return ((struct TreeNode * )a)->data - ((struct TreeNode * )b)->data;
}
void init()
{
	memset(ArrayTree,0,sizeof(ArrayTree));
	memset(used,0,sizeof(used));
	for(int i = 0 ; i < N; i ++)
	{
		ArrayTree[i].deep = 1;
		ArrayTree[i].left = -1;
		ArrayTree[i].right = -1;
	}

}

/* 
用一维数组模拟树的建立  前面end 是排好序的节点 ,也就是之后建好树的叶子节点
以 0 -end -1 和 end - end2 -1  ,后面是编码过程中形成的节点
我认为 最小的节点值  是来自两段数组中 未使用的最前面的节点中最小的 


*/
int GetMinTreeNode(int end ,int end2) // 这里还可以优化 
{
	int i = 0,min1 = 0 ,min2 =end - 1,min;
	for(i = 0 ; i < end2 ; i ++) 
	{
		if(used[i] == 0)
		{
			min1 = i ;
			break;
		}
	}
	for(i = end ; i < end2 ; i ++)
	{
		if(used[i] == 0)
		{
			min2 = i ;
			break;
		}
	}
	//min = min1 < min2 ?min1 :min2;
	//if
	if(ArrayTree[min1].data < ArrayTree[min2].data)
		min = min1;
	else 
		min = min2;
	used[min] = 1;
	return min;

}
void updataTreeNode(int father ,int deep)
{
	int left = ArrayTree[father].left;
	int right = ArrayTree[father].right;
	if(father >= 2)
	{
		if(left != -1)
		{
			ArrayTree[left].deep = deep -1;
			updataTreeNode(left,deep-1);
		}
		if( right != 1 )
		{
			ArrayTree[right].deep = deep -1;
			updataTreeNode(right,deep-1);

		}

	}
}

/* 
用一维数组模拟树的建立 
先排序 后根据哈弗曼算法 开始 建立树 这里我根节点deep 有最大值 ,然后子节点一次递减 

*/
void Hafuman( int end )
{
	qsort(ArrayTree,end,sizeof(struct TreeNode),cmp);
	
	int i,mend = end;
	struct TreeNode tNode;
	for( i = 0 ; i < end -1; i ++)
	{
		tNode.left = GetMinTreeNode(end,end + i) ;
		tNode.right = GetMinTreeNode(end,end + i);
		ArrayTree[tNode.left].father = ArrayTree[tNode.right].father = end + i;
		tNode.data = 	ArrayTree[tNode.left].data  + ArrayTree[tNode.right].data;
		tNode.deep = GetMax(ArrayTree[tNode.left].deep ,ArrayTree[tNode.right].deep ) + 1;
	//	updataTreeNode(end + i,	tNode.deep);//更新其子节点的深度值  这是一个bug 
		ArrayTree[end + i] = tNode;

		updataTreeNode(end + i,	tNode.deep);//更新其子节点的深度值 
		
	}
}
long GetHufuman(int end,int TreeDeep )
{
	int i,result = 0;
	for(i = 0 ; i < end ; i ++)
	{
		result += (TreeDeep - ArrayTree[i].deep )*ArrayTree[i].data;
	}
	return result;
}

int main()
{
	int end,i;
//	freopen("in.txt","r",stdin);
	scanf("%d",&end);
	
	init();
	for(i = 0 ; i < end ; i ++)
		scanf("%d",&ArrayTree[i].data);

	Hafuman(end);
	printf("%d\n",GetHufuman(end,ArrayTree[2*end-2].deep));
	
	
}

你可能感兴趣的:(hafuman 编码)