📌  相关文章
📜  使用Trie排序字符串(或单词)的数组设置2(处理重复项)(1)

📅  最后修改于: 2023-12-03 15:36:37.553000             🧑  作者: Mango

使用Trie排序字符串(或单词)的数组设置2(处理重复项)

使用Trie排序字符串(或单词)的数组设置 中,我们介绍了如何使用 Trie 数据结构对字符串数组进行排序。但是,该方法并没有考虑到数组中存在重复项的情况。因此,在本文中,我们将介绍如何使用 Trie 数据结构处理重复项的情况。

处理重复项

在 Trie 中,每个节点表示一个字符,从根节点开始,到叶子节点形成的单词即为排序后的单词。但是,当原始数组中存在重复项时,可能会出现多个单词以同一路径走过并被存储在 Trie 中的情况。为了避免这种情况,我们可以将 Trie 中的每个节点扩展为一个额外的整数值,用于记录单词出现的次数。

具体来说,我们可以将每个叶子节点的值设置为单词出现的次数。当我们在 Trie 中插入单词时,如果该单词已存在,则只需要将当前节点的值加一,否则,需要创建一个新的叶子节点,其值为 1。

示例代码

以下是使用 C++ 实现的示例代码。其中,TrieNode 表示 Trie 节点,每个节点包括一个布尔值 is_end,用于标记该节点是否为单词的结尾;一个整数值 count,用于记录该节点表示的单词出现的次数;以及一个指向其 26 个子节点的指针数组 childTrie 类包含 insertsort 方法,其中 insert 方法用于将单词插入到 Trie 中,sort 方法则用于对字符串数组进行排序。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

const int ALPHABET_SIZE = 26;

struct TrieNode {
    bool is_end;
    int count;
    TrieNode* child[ALPHABET_SIZE];

    TrieNode() {
        is_end = false;
        count = 0;
        for (int i = 0; i < ALPHABET_SIZE; i++) {
            child[i] = nullptr;
        }
    }
};

class Trie {
public:
    void insert(TrieNode* root, const string& word) {
        TrieNode* node = root;
        for (char c : word) {
            int idx = c - 'a';
            if (node->child[idx] == nullptr) {
                node->child[idx] = new TrieNode();
            }
            node = node->child[idx];
        }
        node->count++;
        node->is_end = true;
    }

    void sort(TrieNode* node, vector<pair<string, int>>& res, string& str) {
        if (node == nullptr) {
            return;
        }
        if (node->is_end) {
            res.push_back({ str, node->count });  // 将单词和出现次数放入结果中
        }
        for (int i = 0; i < ALPHABET_SIZE; i++) {
            str.push_back('a' + i);
            sort(node->child[i], res, str);  // 递归遍历所有子节点
            str.pop_back();
        }
    }
};

vector<pair<string, int>> sort_array(const vector<string>& arr) {
    Trie trie;
    TrieNode* root = new TrieNode();
    for (const string& str : arr) {
        trie.insert(root, str);
    }
    vector<pair<string, int>> res;
    string str;
    trie.sort(root, res, str);
    sort(res.begin(), res.end());  // 将结果按字符串排序
    return res;
}

int main() {
    vector<string> arr = { "apple", "orange", "banana", "apple", "pear" };
    vector<pair<string, int>> res = sort_array(arr);
    for (auto p : res) {
        cout << p.first << " (" << p.second << ")" << endl;
    }
    return 0;
}
总结

本文介绍了如何使用 Trie 数据结构处理字符串数组中存在重复项的情况。具体来说,我们将 Trie 中的每个节点扩展为一个额外的整数值,用于记录单词出现的次数。同时,我们还提供了使用 C++ 实现的示例代码,供读者参考和学习。