问题:如何判断一个字符集是否采用前缀码
【重要】前缀码:任何一个字符的编码都不是同一个字符集中另一个字符的编码的前缀
对于给出的一个字符集,请判断这个字符集是否是前缀码;
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);
}