user-0 提问: [C语言]哈夫曼树问题新手求问

回复:
user: user-1
content: 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

user: user-2
content: 说的甚是详细，谢谢各位大佬的辛苦成果

user: user-3
content: #include <stdio.h> #include <ctype.h> #include <string.h> #include <stdlib.h> #include <malloc.h> #include <windows.h> #define MaxValue 512 #define Maxbit  16  typedef struct { 	char chara; 	int weight; 	int flag; 	int parent; 	int leftchild; 	int rightchild; }haffnode;  typedef struct{ 	int bit[Maxbit]; 	int weight; 	int start; }haffcode;  int my_stdin(void) { 	lb1:fprintf(stderr, "%s", "input num :"); 	char str[1024]; 	fgets(str, 1024, stdin); 		 	int len = strlen(str); 	for(len-1; isspace(str[len-1]) && len >= 0; str[(len--)-1] = '\0') 		; 	 	char *p[1024]; 	int i = 0; 	int j = 0; 	while(str[i]){ 		while(isspace(str[i]) && str[i]) 			++i; 		 		p[j++] = &str[i++]; 		while(isalnum(str[i]) && str[i]) 			++i; 		 		str[i] = '\0'; 		++i; 			 	}  	if(j != 1){ 		fprintf(stderr, "%s\n", "Input error!"); 		fflush(stdin); 		goto lb1; 	} 	 	i = 0; 	int flag = 1; 	while(p[0][i]){ 		if(isdigit(p[0][i])) 			++i; 		else { 			flag = 0; 			break; 		} 			 	} 	 	if(flag == 0){ 		fprintf(stderr, "%s\n", "Input error!"); 		fflush(stdin); 		goto lb1; 	} 	 	int num = atoi(p[0]); 	return num; 	 }    void creat_hafftree(int n, haffnode *hafftree) { 	int i = 0; 	for(; i < 2*n-1; ++i){ 		if(i >= n) 			hafftree[i].weight = 0; 		hafftree[i].flag = 0; 		hafftree[i].parent = -1; 		hafftree[i].leftchild = -1; 		hafftree[i].rightchild = -1; 	} 	 	for(i = 0; i < n-1; ++i){ 		int m1 = MaxValue; 		int m2 = MaxValue; 		int x1 = 0; 		int x2 = 0; 		for(int j = 0; j < n+i; ++j){ 			if(hafftree[j].weight < m1 && hafftree[j].flag == 0){ 				m2 = m1; 				x2 = x1; 				m1 = hafftree[j].weight; 				x1 = j; 			} 			else if(hafftree[j].weight < m2 && hafftree[j].flag == 0){ 				m2 = hafftree[j].weight; 				x2 = j; 			} 		}  		hafftree[x1].parent = n+i; 		hafftree[x2].parent = n+i; 		hafftree[x1].flag = 1; 		hafftree[x2].flag = 1; 		hafftree[n+i].weight = hafftree[x1].weight + hafftree[x2].weight; 		hafftree[n+i].leftchild = x1; 		hafftree[n+i].rightchild = x2; 		 	} 	 	for(i = 0; i < 2*n-1; ++i){ 		printf("%d %2d %2d %2d %2d %2d  \n", i, hafftree[i].weight,\ 		hafftree[i].flag, hafftree[i].parent, hafftree[i].leftchild, hafftree[i].rightchild); 	} 	 	 	return ; }  void haff_code(int n, haffnode *hafftree, haffcode ** code) { 	int i= 0; 	for(; i < n; ++i){ 		code[i] = (haffcode *)malloc(sizeof(haffcode)); 		(haffcode *)memset(code[i], 0x00, sizeof(haffcode)); 		code[i]->weight = hafftree[i].weight; 		code[i]->start = n-1; 		int child = i; 		int parent = hafftree[child].parent; 		 		while(parent != -1){ 			if(hafftree[parent].leftchild == child) 				code[i]->bit[code[i]->start--] = 0; 			else 				code[i]->bit[code[i]->start--] = 1; 			 			child = parent; 			parent = hafftree[child].parent; 		} 		 	} 	 	 	return; }  int main(void) { 	system("cls"); 	fprintf(stderr, "%s\n", "To the number of coding."); 	system("color 04"); 	Sleep(1000); 	system("color 0A"); 	int n; 	n = my_stdin(); 	system("cls"); 	haffnode hafftree[2*n-1]; 	int i = 0; 	for(; i < n; ++i){ 		fprintf(stderr, "%s%d%s", "hafftree[", i, "].chara:"); 		fflush(stdin); 		 		hafftree[i].chara = getchar(); 		 		fprintf(stderr, "%s%d%s\n", "hafftree[", i, "].weight."); 		system("color 04"); 		Sleep(1000); 		system("color 0A"); 		fflush(stdin); 		 		hafftree[i].weight = my_stdin(); 	 	} 	 	creat_hafftree(n, hafftree); 	haffcode *code[n]; 	haff_code(n, hafftree, code); 	 	for(i = 0; i < n; ++i){ 		printf(" chara = %c  weight = %d  ", hafftree[i].chara, code[i]->weight); 		printf("code = "); 		int j; 		for(j = code[i]->start+1; j < n; ++j) 			printf("%d", code[i]->bit[j]); 		printf("\n"); 	} 	 	 	 	return 0; }

user: user-0
content: 引用 5 楼 zhao4zhong1 的回复:代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。 谢谢。 我有详细调试和分析，也找到了问题所在位置，可是不懂为什么会发生这样的问题，也有查询但没有找到结果，所以想问问。

user: user-0
content: 引用 3 楼 user-4 的回复:# include <stdio.h> # define N 1001 void insert(int Tree[],int X);//向堆中插入值 X int Delmin(int Tree[]);  //删除最小值  并返回最小值 int tree[N+1]; long long sum; int main(){     int n,a; 	scanf("%d",&n); 	while(n--) 	{ 		scanf("%d",&a); 		insert(tree,a); 	} 	while(tree[0]>1) 	{ 	   a=Delmin(tree)+Delmin(tree); 	   sum+=a; 	   insert(tree,a); 	} 	printf("%lld\n",sum);     return 0; } void insert(int Tree[],int X) {     int par,i=++Tree[0];       while(i>1)       {        par=(i>>1);         if(Tree[par]<=X) break;          Tree[i]=Tree[par];        i=par;     }     Tree[i]=X; } int Delmin(int Tree[]) {    int i=1,L=2,root=Tree[1],X=Tree[Tree[0]--];    while(L<=Tree[0])    {       L+=L<Tree[0]&&Tree[L+1]<Tree[L];       if(Tree[L]>=X) break;        Tree[i]=Tree[L];       i=L;L=i<<1;    }    Tree[i]=X;    return  root; }  把这个代码交上去 保证又快又对 谢谢，可是我想知道自己的为什么不对呀

user: user-4
content: # include <stdio.h> # define N 1001 void insert(int Tree[],int X);//向堆中插入值 X int Delmin(int Tree[]);  //删除最小值  并返回最小值 int tree[N+1]; long long sum; int main(){     int n,a; 	scanf("%d",&n); 	while(n--) 	{ 		scanf("%d",&a); 		insert(tree,a); 	} 	while(tree[0]>1) 	{ 	   a=Delmin(tree)+Delmin(tree); 	   sum+=a; 	   insert(tree,a); 	} 	printf("%lld\n",sum);     return 0; } void insert(int Tree[],int X) {     int par,i=++Tree[0];       while(i>1)       {        par=(i>>1);         if(Tree[par]<=X) break;          Tree[i]=Tree[par];        i=par;     }     Tree[i]=X; } int Delmin(int Tree[]) {    int i=1,L=2,root=Tree[1],X=Tree[Tree[0]--];    while(L<=Tree[0])    {       L+=L<Tree[0]&&Tree[L+1]<Tree[L];       if(Tree[L]>=X) break;        Tree[i]=Tree[L];       i=L;L=i<<1;    }    Tree[i]=X;    return  root; }  把这个代码交上去 保证又快又对

user: user-4
content: # include <stdio.h>  //WEI行 N列的优先队列    # define N 20001   void insert(int Tree[],int X);//向堆中插入值 S[WEI]    int Delmin(int Tree[]);  //删除最小值-并返回最小值   int tree[N+1];   long long sum;         int main(){       int n,a; 	scanf("%d",&n); 	while(n--) 	{ 		scanf("%d",&a); 		insert(tree,a); 	} 	while(tree[0]>1) 	{ 	   a=Delmin(tree)+Delmin(tree); 	   sum+=a; 	   insert(tree,a); 	} 	printf("%lld\n",sum);     return 0;   }   void insert(int Tree[],int X)       {           int par,i=++Tree[0];  //插入X 后 Tree[0]+1           while(i>1)  //直到i不是根节点           {              par=(i>>1);  //父节点为par              if(Tree[par]<=X) break;   //将<=改为>=即改为最大堆了          Tree[i]=Tree[par]; //否则调整堆 即位置上移              i=par;           }           Tree[i]=X;//插入新节点       }       int Delmin(int Tree[])       {          int i=1,L=2,root=Tree[1],X=Tree[Tree[0]--];         while(L<=Tree[0])          {                 L+=L<Tree[0]&&Tree[L+1]<Tree[L];       if(Tree[L]>=X) break;         //并且将>=改为<=即为最大堆         Tree[i]=Tree[L];//否则继续调整堆             i=L;L=i<<1;     }          Tree[i]=X;      return  root;       }   如果单纯求权值 直接用堆  速度快

user: user-0
content: 测试结果如上