电子小字典(查找)
[问题描述]
利用键树结构,建立一个微型电子字典。
[基本要求]
实现生词的加入,单词的查找、删除,修改等操作。
解题思路:
首先对键树结构进行解释。这里,我们每个节点中并不是一个或几个关键字,而是只含有组成关键字的符号。在这题中,每个节点只包含组成单词的字母。我们用结构体数组(vector类型)来存储键树,原键树的节点在这里对应数组的一格。先在“字典”中初始化26个英文字母(小写),作为插入、查询等的起始位置。
插入:对要插入单词的字母进行逐个遍历,先匹配字典中已有的部分,例如原来已有“be”,再插入“bean”时,就会先匹配be的部分,之后an的部分会在vector后面按顺序添加,最后将末尾字母的end置为1,代表一个单词插入完成。查询时,按照next进行追踪即可。删除:先查询,若查询成功,则获得末尾字母的编号,把末尾字母的end重新置为0,则删除成功;若查询失败,则插入失败。修改:考虑到修改的方式多种多样,可能是减短、增长或改变几个字母等,为了简便,这里就直接把原单词删除,再把修改后的单词插入到字典中。
程序代码:
# include <iostream>
# include <stdlib.h>
# include <string>
# include <vector>
using namespace std;
typedef struct Alphabet {
char a; //字母
int end; //是否为单词结尾(0:否 1:是)
vector<int>next;
}Alphabet;
//操作菜单
void Menu();
//添加单词
void InsertWord(string str);
//查询单词
int SearchWord(string str);
//删除单词
void DeleteWord(string str);
//修改单词
void ChangeWord(string str1, string str);
int num = 0; //保存当前的数组长度
vector<Alphabet>word; //字典
//主函数
int main()
{
//初始化字典
Alphabet al;
for (int i = 0; i < 26; i++) {
al.a = 97 + i;
al.end = 0;
word.push_back(al);
num++;
}
int select;
while (1) {
int t;
string str, str1;
Menu();
cout << "请选择:";
cin >> select;
if (select == 1) {
//添加单词
cout << "请输入要添加的单词:";
cin >> str;
InsertWord(str);
}
else if (select == 2) {
//查询单词
cout << "请输入要查询的单词:";
cin >> str;
t = SearchWord(str);
if (t >= 0) {
cout << "查询成功" << endl;
}
else {
cout << "查询失败" << endl;
}
}
else if (select == 3) {
//删除单词
cout << "请输入要删除的单词:";
cin >> str;
DeleteWord(str);
}
else if (select == 4) {
//修改单词
cout << "请输入要修改的单词:";
cin >> str1;
cout << "请输入修改后的单词:";
cin >> str;
ChangeWord(str1, str);
}
else {
break;
}
}
return 0;
}
//操作菜单
void Menu()
{
cout << "\n*******************************\n";
cout << "**(1)、添加单词 *************\n";
cout << "**(2)、查询单词 *************\n";
cout << "**(3)、删除单词 *************\n";
cout << "**(4)、修改单词 *************\n";
cout << "**(5)、退出 *****************\n";
cout << "*******************************\n";
}
//添加单词
void InsertWord(string str)
{
Alphabet al;
int j = str[0] - 97; //字母
int t, i;
for (i = 1; i < str.size(); i++) {
t = 0;
for (int k = 0; k < word[j].next.size(); k++) {
int m = word[j].next[k];
if (word[m].a == str[i]) {
j = m;
t = 1;
break;
}
}
if (!t) {
//到此能遍历的单词部分
break;
}
}
while (i < str.size()) {
//单词没有遍历完
al.a = str[i];
al.end = 0;
word[j].next.push_back(num);
word.push_back(al);
j = num;
num++;
i++;
}
word[j].end = 1;
}
//查询单词
int SearchWord(string str)
{
int j = str[0] - 97; //字母
int t, i;
for (i = 1; i < str.size(); i++) {
t = 0;
for (int k = 0; k < word[j].next.size(); k++) {
int m = word[j].next[k];
if (word[m].a == str[i]) {
j = m;
t = 1;
break;
}
}
if (!t) {
//到此能遍历的单词部分
break;
}
}
if (i == str.size() && word[j].end) {
return j;
}
else {
return -1;
}
}
//删除单词
void DeleteWord(string str)
{
int t = SearchWord(str);
if (t >= 0) {
word[t].end = 0;
cout << "删除成功" << endl;
}
else {
cout << "删除失败" << endl;
}
}
//修改单词
void ChangeWord(string str1, string str)
{
int t = SearchWord(str1);
if (t >= 0) {
word[t].end = 0;
InsertWord(str);
cout << "修改成功" << endl;
}
else {
cout << "修改失败" << endl;
}
}
总结:
这种写法比较简单,但也有一定的缺点。对于单词的删除,我只是做了形式上的“删除”,保证其无法再被查询到,但其占据的空间还在,这样会导致空间的浪费。大家可以尝试自己改进。
以上是我对这道题的看法,很高兴与大家分享。