/*
* poj 1056 IMMEDIATE DECODABILITY
题目大意:
前缀编码方式可以保证任何字符的编码不是另外一个字符编码的前缀。本题给出一些编码方式,
判断该编码方式是否是前缀编码。
解题思路:
方法1:
按照给定的编码建立radix树,边读入编码边插入树,发现某编码是另外编码的前缀即停。
没发现前缀,则该编码是前缀编码。
方法2:
读入全部编码,按照字典序排序。检测相邻的字串是否存在前缀关系,有就停止,没有即
是前缀编码。
比较:
方法1:
优点: 可能无需全部读入即可判断非前缀编码;前缀判断简单。
缺点: 需要动态申请、释放内存,这部分应该是占时间最多的。不过因为题目中说了
字串最长8个字节,所以树高最大8,最多511个节点,可以采用数组的方式实
现树结构,从而避免了这部分时间的浪费。
方法2:
优点: 无需动态申请内存。
缺点: 排序浪费时间;前缀判断浪费时间。
本题采用方法1解。
延展:
huffman编码就是前缀编码方式。huffman编码的实现及原理。
discuss上管这个树叫TRIE,其实对于字符表只有0和1的情况应该叫radix树,比trie还是有差别的。
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
namespace {
using namespace std;
typedef struct NODE
{
int left, right;
}NODE_S;
const int N_MAX = 512;
int available_index = 1;
NODE_S radix[N_MAX];
#define ALLOC_NODE(index) \
do \
{ \
index = available_index; \
available_index += 1; \
} while(0)
// 判断是否叶子节点
inline bool is_leaf(int index)
{
if (0 == index) // 根永远不是叶子
return false;
return (0==radix[index].left && 0==radix[index].right);
}
bool try_insert(const char *code)
{
int parent=0, child;
// 按照已有的radix树搜索
int i;
for (i=0; code[i]!='\0'; i++)
{
if (code[i] == '0')
child = radix[parent].left;
else
child = radix[parent].right;
if (child==0)
break;
else
parent = child;
}
// 待插入的串相对较短
if (code[i]=='\0')
return false;
if (child==0 && is_leaf(parent))
return false; // 非前缀编码,已经判定
// 把剩下的部分插入radix树
for (; code[i]!='\0'; i++)
{
ALLOC_NODE(child);
if (code[i] == '0')
radix[parent].left = child;
else
radix[parent].right = child;
parent = child;
}
return true;
}
}
int main()
{
int set_no = 1;
char code[16];
while (EOF != scanf("%s", code))
{
available_index = 1;
memset(radix, 0, sizeof(radix));
bool bJudged = false;
while (code[0] != '9')
{
if (!bJudged && !try_insert(code))
{
bJudged = true;
printf("Set %d is not immediately decodable\n", set_no);
}
scanf("%s", code);
}
if (!bJudged)
printf("Set %d is immediately decodable\n", set_no);
set_no++;
}
return 0;
}
poj 1056 IMMEDIATE DECODABILITY -- radix tree应用
最新推荐文章于 2017-03-23 20:18:59 发布