【问题标题】:AVL tree: practical use of dictionaryAVL树:字典的实际使用
【发布时间】:2019-12-30 21:05:36
【问题描述】:

我想使用 AVL 树结构作为字典下的基础。 我的班级:

template <typename keyType, typename dataType>
class AVLTree
{
  class Node
  {
  public:
         keyType key;
         dataType data;
         short int balanceFactor;
         Node * left;
         Node * right;

         Node(const keyType & newKey, const dataType & newData) : key(newKey), data(newData), balanceFactor(0), left(NULL), right(NULL) {};
  };
  Node * Root;
***methods
void insert(AVLTree<keyType, dataType>::Node* & subtreeRoot,  const keyType & newKey, const dataType & newData); //insert new element
  void clear(AVLTree<keyType, dataType>::Node* & subtreeRoot); //clear whole tree
  void graph(AVLTree<keyType, dataType>::Node* const & subtreeRoot, int indent) const; //print tree
  void printDes(AVLTree<keyType, dataType>::Node* const & subtreeRoot) const; //print in descending order
  void printAsc(AVLTree<keyType, dataType>::Node* const & subtreeRoot) const; //print in ascending order
...
public:
  void search(const keyType & findKey) const;
...};

假设我得到一个句子:

我喜欢绿草和绿树。

当我去掉标点符号 ('.') 并降低我得到的所有单词时:

我喜欢绿草和绿树

我想把每个单词都放在AVL树的结构中,并打印为升序列表:

和- 1

草-1

绿色- 2

i -1

喜欢- 1

树木- 1

其中第二个“参数”是出现次数,即在 green 的情况下为 2。

我已经将它作为单链表的映射,但现在我想实现 AVL 树,我想知道下一步应该做什么。我打算用几种方法制作一个外部类 COUNTER,包括这个。我的想法:

  1. 遍历句子;如果单词 (key) 不存在(search 方法返回通知 - 应该变成布尔值?),添加它(insert 方法) 到树上。

  2. 如果它已经存在,增加第二个参数(在这种情况下,data)--- 如何? 如果没有,请将其添加到 data=1 的树中。

那么,最后一个问题是:我的想法正确吗?如果是这样,那么如何增加模板的第二个参数呢?迭代器是解决这个问题的方法吗?


编辑: 这是我使用单链表的实现,但没有使用 INFO:

template <typename key>
class counter {
sequence<key> list;
std::map<string, int> map;

public:
void add_word(key new_word) {
    list.insertEnd(new_word);

    auto iterator = map.find(new_word);
    if (iterator != map.end()) {
        iterator->second++;
    } else {
        map.insert({new_word, 1});
    }
}

我想知道它可能会起作用:

template <typename key, typename info>
class counter {
AVLTree<key, info> dict;
std::map<string, int> map;

public:
void add_word(key new_word) {
    dict.insert(new_word,1);

    auto iterator = map.find(new_word);
    if (iterator != map.end()) {
        iterator->second++;
    } else {
        map.insert({new_word, 1});
    }
}
...}

但我想它不会那样工作

【问题讨论】:

  • 如果你能让你的AVL树类有和std::map一样的接口就好了。

标签: c++ dictionary avl-tree


【解决方案1】:

所以给定data 是你想要增加的值,并且它是某种整数类型,你可以简单地做

++found_node->data; 

这就是“增加模板的第二个参数”的意思吗?

请注意,您的代码示例中的search 方法不会返回任何内容。它可能应该将Node* 或某个迭代器返回到找到的节点(或nullptr / end-iterator)。

这对你有帮助吗?

【讨论】:

    【解决方案2】:

    是的,您可以修改 search 以返回 bool(但这取决于您希望如何使用它)。如果搜索返回false,则必须调用insert

    您似乎没有明确区分要向 AVLtree-map 用户公开的 API。

    增加第二个参数(在本例中为数据)--- 如何?

    这取决于您的用例,但让我提出一些建议。您在您的Node 中将此计数保持为卫星data。通常,映射被实现为一棵树,其中节点(持有键)指向相应的值。在您的情况下,您只需要跟踪计数。将它存储在节点中是一个好主意(正如您已经完成的那样)。我更喜欢通用的insert 函数,它只接受key

    insert 将遍历树,如果元素已经存在,则搜索(searchinsert 中调用表单)。如果存在,它只会增加与持有密钥的节点关联的计数器。否则,它将创建一个新的Node,并将data 设置为1

    您的AVLTree 将被实例化为AVLTree&lt;string, int&gt; tree。当我第一次调用tree.insert("green") 时,我希望关联的data 值设置为1。如果我下次调用tree.insert("green"),它应该设置为2

    请注意,您的 map 缺少一个关键的 API,该 API 服务于“与此键关联的值/数据是什么,k?”。 tree.get("green"),应该返回计数。

    map 用户不会关心隔离输入和准备外部计数。 map 必须处理这个问题。在外面做and- 1, grass- 1, green- 2, i -1, like- 1, trees- 1 表单可能不是你想要的。

    正如 Sliepen 在 cmets 中提到的,我正试图将其更接近 std::map 公开的接口。


    如前所述,由您决定find/search 是否返回bool/Node*。但是如果你决定返回一个Node*,一个可能的实现是,

    Node* foundNode = find(word)
    if(!foundNode) 
        insert(word) //this should construct a `new` node with count/data to be 1
    else foundNode->data++;
    

    【讨论】:

    • 类计数器 { AVLTree dict; std::map 地图;公共:无效add_word(key new_word){dict.insertN(new_word,1);自动迭代器 = map.find(new_word); if (iterator != map.end()) { iterator->second++; } else { map.insert({new_word, 1}); } } ...};但是时间,与 LIST 的使用(列表只有 KEY,没有 INFO 参数)相比,几乎是 4 倍,而使用树应该更小......
    • @Marta 我不完全确定你打算在这里做什么。为什么你有一个 counter 类同时具有 AVLTreestd::map ?据我了解,您正在尝试为 &lt;key, value&gt; 存储映射 words# of AVLTree 字典>发生。如果是,那么拥有地图是多余的。 std::maps 建立在红黑树之上(比 AVL 更快)。另外,您能否编辑问题并将此(以及更多)代码粘贴到那里?我会很容易阅读。
    • @rrjanjik,我的意图是在 AVLTree 类之外创建函数(方法),它将打印出文本文件中不同单词的出现次数,但在这种情况下,而不是使用简单的单链接用于例如的列表搜索这个词,我正在使用 AVL 树。我稍微修改了一下帖子,如果有什么需要,我会添加更多。
    • 或者使用 SLL 发布带有解决方案的代码将清楚我想用 AVL 树做什么
    • @Marta 刚刚看到您的编辑。谢谢。我仍然认为counter 不需要AVLTreestd::map。我会在某个时候回到这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多