MOOC 课后讨论5.2 判别是否是前缀码的算法

问题:如何判断一个字符集是否采用前缀码

【重要】前缀码:任何一个字符的编码都不是同一个字符集中另一个字符的编码的前缀

对于给出的一个字符集,请判断这个字符集是否是前缀码;

Input Specification:

输入包含若干行测试数据。每组数据的第一行给出正整数N 为该字符集的字符个数 和MAXbit 为该编码最多位数 随后给出N行 每行为该字符集每个字符的二进制编码

Output Specification:

如果该字符集是前缀码,输出"Yes" 否则输出"No"

Sample Input 1:

5 3
00
01
10
110
111

 Sample Output 1:

Yes

Sample Input 2:

8 4
00
010
0110
0111
10
11
1110
111
  • 思路根据给出的字符集来栽树,每个字符的每位二进制为一个结点,最后一个二进制为叶结点,作一个标记Sign,如果另一个字符的编码经过有标志的结点,则说明不是前缀码;

  • 如果将权重值赋给标记,配合strlen 还可以求出权路径长度(WPL)= Sign*strlen(Bit)

/* 结构和函数设计 */

#include <stdio.h>
#include <stdlib.h>                    
 
typedef struct _Node Tree; //个人习惯指针带* 

struct _Node{
	int Sign; //将每个字符编码的最后一个结点 Sign=1 标记为叶结点,如果有其他编码经过 则不是前缀码  
	Tree* Left;
	Tree* Right; //二进制0 为有左树  1 为有右树
};

Tree* MakeTree( int N,int MAXbit,int* P );

Tree* NewNode( );

Tree* Insert(Tree* Temp,char bit,int* P );

void FreeTree( Tree* BT );

/* 程序主框架 */

int main()
{
	//根据IsPrefixCode的值判断是否为前缀码;
	int N,MAXbit,IsPrefixCode = 1; 
	
	scanf("%d %d",&N,&MAXbit);
	
	//根据N行 最多MAXbit位 的二进制 来栽树;并带出IsPrefixCode的值;
	Tree* BT = MakeTree( N,MAXbit,&IsPrefixCode ); 
	
	if(IsPrefixCode){
		printf("Yes\n");
	}else{
		printf("No\n");
	}
	
	FreeTree( BT );
	
	return 0;
}
  • 栽树函数  P是 变量 IsPrefixCode 的地址

Tree* MakeTree( int N,int MAXbit,int* P )
{
	Tree* BT = NewNode( );
	
	char Bit[MAXbit+1];  //数组表示字符串 记得多一位放'\0'哦
	
	Tree* Temp;

	while(N--){
		scanf("%s",Bit);
		
		Temp = BT;
		
		for(int i=0;Bit[i] != '\0';i++){
  
				Temp = Insert( Temp,Bit[i],P );
		}
		/*这里也可以求字符串长度 strlen(Bit)来作循环for(i=0;i<strlen(Bit);i++)
    同时将权重赋给标记,就可以求出带权路径长度(WPL)= Sign*strlen(Bit)*/

		if(Temp->Left || Temp->Right){ //一个字符编码建树完成后 如果最后不是叶结点 则不是前缀码
			*P = 0;
		}else{
			Temp->Sign = 1; //也可以将权重值赋给叶结点 Temp->Sign = Weight,方便后面求带权路径长度(WPL)
		}
		
	}
	
	return BT;
}
  • 核心  插入函数 —— 插入的过程中 如果有经过Sign == 1 的结点,或者插入最后一位时,已经有结点了,则说明不是前缀码。函数返回的是最后的位置 以方便下一个结点插入

Tree* Insert(Tree* Temp,char bit,int* P )
{
	if(bit == '0'){
		if(Temp->Left){
			Temp = Temp->Left;

		}else{
			Temp->Left = NewNode( );
			Temp = Temp->Left;
		}
	}else{
		if(Temp->Right){
			Temp = Temp->Right;

		}else{
			Temp->Right = NewNode( );
			Temp = Temp->Right;
		}
	}
	
	if(Temp->Sign){  //插入的过程中经过有标记的结点,则不是前缀码
		*P = 0;
	}
	
	return Temp;
}
  • 新建结点函数

Tree* NewNode( )
{
	Tree* newNode = (Tree*)malloc(sizeof(Tree));
	
	newNode->Left = newNode->Right = NULL;
	newNode->Sign = 0;

	
	return newNode;
}
  • 最后别忘了 有malloc 就有free

void FreeTree( Tree* BT )
{
	if(BT->Left){
		FreeTree( BT->Left );
	}
	if(BT->Right){
		FreeTree( BT->Right );
	}
	
	free(BT);
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
工程伦理MOOC课后讨论题答案分为以下几个方面: 首先,对于职业道德方面的问题,工程师应该始终遵循职业道德准则,并保持诚实、正直的态度。工程师应该严守法律法规,并遵守行业规范,确保工程项目的质量和安全。 其次,工程师应考虑到自身的专业发展和技能提升。他们应该持续学习、研究新的技术和方法,不断提高自己的能力,以适应不断变化的工程环境。 另外,工程师需要在项目中找到平衡点。他们需要协调不同利益方的需求,并确保公正性和客观性。他们应该考虑到环境保护、社会责任等方面的因素,并尽量减少对环境的负面影响。 与此同时,工程师还应该关注权力的滥用问题。他们应该避免利用职位的权力谋取不当利益,不使用职务之便为自己谋取私利。 此外,对于工程项目的决策和风险评估,工程师应该全面考虑各种可能的结果和影响,并选择最佳解决方案,同时:根据科学的数据和证据作出决策,以达到最佳结果。 最后,工程师还应该关注个人和团队的职业发展和道德培训。他们应该定期进行道德讨论和反思,不断提高自身道德素养,并鼓励团队成员之间进行互相监督和提醒,共同维护工程伦理的尊严和荣誉。 总之,工程伦理MOOC课程的讨论题提供了一个平台,引导工程师思考和探讨伦理问题,并帮助他们在实践中遵循道德准则,提高自身素养,推动工程伦理的发展和进步。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值