读完一个嘀嘀或嘀嘀后,你有两个选择:终止这封信或继续当前的信。这将导致您的代码出现很多分歧,而递归方法可能是实现这一点的好方法。
到目前为止,保留可能字符串的缓冲区,并在您碰到字符串结尾并且与字母结尾重合时打印(或存储)结果。
这是 C 中的一个实现:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static const char *letter = "**ETIANMSURWDKGOHVF*L*PJBXCYZQ**";
void morse_r(char *buf, int len, const char *str, int code)
{
if (*str == '\0') {
// end of string; print if staring new letter
if (code == 1) printf("%.*s\n", len, buf);
} else if (code < 16) {
if (*str == '.') code = 2 * code;
if (*str == '-') code = 2 * code + 1;
// continue letter
morse_r(buf, len, str + 1, code);
// start new letter
buf[len++] = letter[code];
morse_r(buf, len, str + 1, 1);
}
}
void morse(const char *str)
{
char buf[strlen(str)];
morse_r(buf, 0, str, 1);
}
int main()
{
morse("......-...-..---");
return 0;
}
这个实现非常简单。它使用简单的查找机制,并且不检查字母是否确实存在。 (letter 数组中的星号是有效的摩尔斯电码,但它们不是拉丁字母。)
这种方法也相当暴力:它一遍又一遍地重新计算尾部。尾部的记忆将为处理孤独字符串的处理器节省大量额外的工作。
而且,正如您所知,会有很多无意义的结果。上面的代码产生 20569 个字符串(其中一些带有星号,即无效)。当您在途中进行合理性或字典检查时,您可以防止许多递归。例如,一行中的许多点会产生很多带有重复 Es 的无意义词。
编辑: 正如 Jim Mischel 所指出的,按顺序解释摩尔斯电码查找的工作原理。 Yves Daoust 在他的回答中提到了一个 trie。一个trie是一个用于存储单词的树形结构;每个节点可以有与字母表中的字母一样多的子节点。摩尔斯电码只有两个字母:dit (.) 和 dah (-)。因此,摩尔斯电码树是二叉树。
尝试通常很少;单词相当长,许多字母组合不存在。莫尔斯尝试是密集的:莫尔斯字母编码很短,几乎每个组合都被使用。树可以存储为线性的“平面”数组,类似于heap。一个节点由它在数组中的索引i 表示。那么左孩子是2*i,右孩子是2*i + 1。
可以在answer I posted 中找到另一个与莫尔斯相关的问题的更好和更详细的解释,我从中获取了我在上面示例中使用的查找代码。