Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何创建单词阶梯?_C++_Linked List_Queue - Fatal编程技术网

C++ 如何创建单词阶梯?

C++ 如何创建单词阶梯?,c++,linked-list,queue,C++,Linked List,Queue,我正在尝试创建一个单词阶梯,使用一个链接列表作为单词字典,并使用一个队列来保存要更改的单词 在队列的while循环中,它到达字典中的第一个单词(单词“toon”,并更改为“poon”)并停止。我怎样才能让它继续下去,直到达到目标词 代码如下: #include <iostream> #include <queue> #include <stack> #include <string> using namespace std; struct Nod

我正在尝试创建一个单词阶梯,使用一个链接列表作为单词字典,并使用一个队列来保存要更改的单词

在队列的
while
循环中,它到达字典中的第一个单词(单词
“toon”
,并更改为
“poon”
)并停止。我怎样才能让它继续下去,直到达到目标词

代码如下:

#include <iostream>
#include <queue>
#include <stack>
#include <string>
using namespace std;

struct Node
{
    string data;
    Node* next;
};

void insert(string ele, Node*& head)
{
    Node* newnode = new Node;
    newnode->data = ele;
    newnode->next = head;
    head = newnode;
}

void del(string key, Node*& head)
{
    Node* temp = head;
    Node* prev = NULL;

    if (temp != NULL && temp->data == key)
    {
        head = temp->next; 
        delete temp;            
        return;
    }
    else
    {
        while (temp != NULL && temp->data != key)
        {
            prev = temp;
            temp = temp->next;
        }
        if (temp == NULL)
            return;

        prev->next = temp->next;

        delete temp;
    }
}

bool find(string key,Node *&head)
{
    Node* p = head;
    while (p != NULL)
    {
        if (p->data == key)
        {
            return true;
        }
        else
        {
            p = p->next;
        }
    }
    if (p == NULL)
        return false;
}

void print(Node*& head)
{
    Node* p = head;
    while (p != NULL)
    {
        cout << p->data;
        p = p->next;
    }
}

void WordLadder(string start, string target, Node*& head)
{
    if (start == target)
        cout << "They are the same";

    if (find(target, head) != true)
        cout << "Target Not found in dicionary";
    //start word size
    int wordlength = start.size();
    //counter
    int level = 0;
    queue<string> q;
    //push word in queue
    q.push(start);
    int len = 0;
    while (!q.empty())
    {
        int wordlength = start.size();
        int sizeofq = q.size();
       
        string word = q.front();
        q.pop();
        for (int i = 0; i < wordlength ; i++)
        {
            for (char c = 'a'; c <= 'z'; c++)
            {
                word[i] = c;
                   
                if (word == target)
                {
                    q.pop();
                }
                if (find(word, head) == true)
                {
                    del(word, head);
                    q.push(word);
                    break;
                }
            }
        }
    }
    cout << len;
}

int main()
{
    Node* head = NULL;
    insert("poon", head);
    insert("plee", head);
    insert("same", head);
    insert("poie", head);
    insert("plie", head);
    insert("poin", head);
    insert("plea", head);
    string start = "toon";
    string target = "plea";
    
    WordLadder(start, target, head);
   
    return 0;
}
#包括
#包括
#包括
#包括
使用名称空间std;
结构体类型
{
字符串数据;
节点*下一步;
};
无效插入(字符串元素、节点*&头)
{
Node*newnode=新节点;
newnode->data=ele;
新建节点->下一步=头部;
头=新节点;
}
void del(字符串键、节点*&头)
{
节点*温度=头部;
Node*prev=NULL;
if(temp!=NULL&&temp->data==key)
{
头=温度->下一步;
删除临时文件;
返回;
}
其他的
{
while(temp!=NULL&&temp->data!=key)
{
prev=温度;
温度=温度->下一步;
}
if(temp==NULL)
返回;
上一个->下一个=临时->下一个;
删除临时文件;
}
}
布尔查找(字符串键、节点*&头)
{
节点*p=头部;
while(p!=NULL)
{
如果(p->data==键)
{
返回true;
}
其他的
{
p=p->next;
}
}
if(p==NULL)
返回false;
}
无效打印(节点*&头)
{
节点*p=头部;
while(p!=NULL)
{
cout数据;
p=p->next;
}
}
无效字梯(字符串开始、字符串目标、节点*&头)
{
如果(开始==目标)
cout算法
看起来您的思路是正确的,尝试实现类似BFS的东西,所以我不打算详细解释“字梯”的算法。
但一个高层次的概述是:

  • 将起始字推送到队列中
  • 运行循环,直到队列为空
  • 遍历与当前单词仅相差一个字符的所有单词,然后 将单词推入队列(对于BFS)
  • 重复,直到我们找到目标单词或通读所有单词
  • 您所犯的错误以及我如何修复这些错误: 在“wordlength”循环之前,您需要一个循环来遍历队列上的所有元素。虽然
    While
    循环似乎正在这样做,但事实并非如此。我想您已经意识到这一点,因为您创建了
    sizeofq
    变量,但从未使用过它。该循环如下所示:

    for(int j = 0; j < sizeofq; j++) {
    
    文体建议 <>你似乎是一个新的C++程序员,所以我想我会把我的想法留给这里的代码。 让函数
    返回结果,而不是打印结果,这被认为是一种很好的做法。它使您的代码更加灵活

    你实现了自己的容器来完成这项工作,这有点像是重新发明轮子。C++ STL几乎总是包含一些可以让你的生活变得更容易的东西,所以在你开始工作之前就要搜索它。


    如果你写的是一个更大的项目,不要使用<代码> >命名空间< /C> >,但是对于一个像这样的小玩具,它是好的。

    < P>我已经在我的一个答案中说过,在C++中滚动你自己的容器常常会导致混淆和难以阅读的代码,这在解决问题时毫无帮助。 <>在现代C++(即C++ 11之后,现在理想地你应该使用C++ 17,甚至开始与C++ 20进行严格的交互),你几乎不需要像<代码>运算符new <代码>,<代码> null < /C>和指针(它们仍然是一个临时的解决方案,因为缺少<代码> STD::可选的< /C> >) 顺便说一句,我不认为需要使用队列来解决您的问题;一个“当前项”变量就足够了;然后,您可以通过搜索与当前元素的汉明距离为1的字符串列表来查找下一个元素。由于循环的可能性,它在一般情况下不起作用,但如果您只处理有限的单词列表,例如您的单词列表,而实际上只有一个可能的lad,那么它就足够了德

    这就是我如何在C++20中快速建模您的问题:

    #include <algorithm>
    #include <cstdlib>
    #include <iostream>
    #include <ranges>
    #include <stdexcept>
    #include <string>
    #include <string_view>
    #include <vector>
    
    using namespace std::literals;
    
    // Simple implementation of Hamming's distance (see https://en.wikipedia.org/wiki/Hamming_distance)
    std::size_t hamming_distance(const std::string_view s1, const std::string_view s2) {
        std::size_t dist {};
    
        if (s1.size() != s2.size()) {
            throw std::runtime_error { "strings have different lengths, which is unsupported" };
        }
    
        auto it1 { s1.begin() };
        auto it2 { s2.begin() };
    
        const auto end1 { s1.end() };
    
        while (it1 != end1) {
            dist += *it1++ != *it2++;
        }
    
        return dist;
    }
    
    bool word_ladder(std::string_view start, const std::string_view target, std::vector<std::string> words) {
        if (start == target) {
            std::cout << "noop: start and target are the same\n";
            
            return true;
        }
    
        // C++20's ranges - use std::find(std::begin(words), std::end(words), target) in older revisions
        if (std::ranges::find(words, target) == std::end(words)) {
            std::cerr << "error: target Not found in dictionary\n";
    
            return false;
        }
    
        std::size_t len { 1U };
    
        // Current word in the ladder - must be string because we are deleting them from the vector,
        // so we must copy them
        std::string word { start };
    
        std::cout << word;
    
        while (word != target) {
            std::cout << "->";
    
            // find an element in the dictionary has hamming(el, word) == 1 (i.e. 'cord' and 'core').
            // this won't work if there's more than one match, because it will cause a loop.
            // This is also based on C++20's ranges, and it can be replaced with std::find_if
            const auto next_it { std::ranges::find_if(words, [word] (const auto el) { return hamming_distance(el, word) == 1; }) };
    
            // no match, it means the chain can't be completed
            if (next_it == std::end(words)) {
                std::cout << "X (no result)\n";
    
                return false;
            }
    
            // print the next element
            std::cout << *next_it;
          
            // set the next word as the newly found item
            word = *next_it;
    
            // remove it from the vector
            // while this is O(n), it's empirically as fast as using a more "optimized" container
            // due to how hecking fast vectors and memcpy are on modern CPUs
            words.erase(next_it); 
    
            ++len; // chain length counter
        }
    
        std::cout << "\nChain was " << len << " elements long\n";
    
        return true;
    }
    
    int main() {
        std::vector<std::string> words {
            "poon",
            "plee",
            "same",
            "poie",
            "plie",
            "poin",
            "plea",
        };
    
        const auto start { "toon"sv };
        const auto target { "plea"sv };
        
        const bool success { word_ladder(start, target, std::move(words)) };
       
        return success ? EXIT_SUCCESS : EXIT_FAILURE;
    } 
    
    我使用了
    std::vector
    而不是一个更“最优”的容器,因为它通常是最好的全方位选择,即使是在非常有限的系统上,因为现代CPU的速度有多快。链表尤其糟糕,应该(几乎)如此由于指针间接性带来的巨大开销,总是避免使用,这抵消了您可能从中获得的任何理论收益


    通常,您应该使用向量和hashmap(即std::unordered_map)默认情况下,只在你真正需要的时候考虑其他容器。

    看起来你想用一种与BFS非常相似的算法。你可以尝试搜索它是如何建立的。我会尝试修复你的代码。你的代码看起来像C和C++之间的混合。你肯定应该重新实现一个链表。(STL中已有
    std::list
    ,用于
    std::string
    std::queue
    ),b.为什么你要使用诸如
    NULL
    操作符new
    和裸指针之类的东西,而不是智能指针和移动语义和c.为什么你要首先使用链表?链表在现代机器上效率极低,与
    vector
    deque。此外,我会远离指针引用(即T*&)-事情可能会变得非常混乱。如果有任何方法比链表更好,请告诉我-如果您确实需要链表,只需使用
    std::vector
    std::list
    (提示:您不需要)。如果没有很好的理由,重新发明轮子通常会导致代码质量下降,更难理解。在这里,我建议使用一些具有良好“查找”功能的数据结构(尽管您可以只对
    std::vector
    进行排序)。我会使用一个
    std::set
    。仔细阅读每一个的推荐用法,并为每一个选择最佳用法
    #include <algorithm>
    #include <cstdlib>
    #include <iostream>
    #include <ranges>
    #include <stdexcept>
    #include <string>
    #include <string_view>
    #include <vector>
    
    using namespace std::literals;
    
    // Simple implementation of Hamming's distance (see https://en.wikipedia.org/wiki/Hamming_distance)
    std::size_t hamming_distance(const std::string_view s1, const std::string_view s2) {
        std::size_t dist {};
    
        if (s1.size() != s2.size()) {
            throw std::runtime_error { "strings have different lengths, which is unsupported" };
        }
    
        auto it1 { s1.begin() };
        auto it2 { s2.begin() };
    
        const auto end1 { s1.end() };
    
        while (it1 != end1) {
            dist += *it1++ != *it2++;
        }
    
        return dist;
    }
    
    bool word_ladder(std::string_view start, const std::string_view target, std::vector<std::string> words) {
        if (start == target) {
            std::cout << "noop: start and target are the same\n";
            
            return true;
        }
    
        // C++20's ranges - use std::find(std::begin(words), std::end(words), target) in older revisions
        if (std::ranges::find(words, target) == std::end(words)) {
            std::cerr << "error: target Not found in dictionary\n";
    
            return false;
        }
    
        std::size_t len { 1U };
    
        // Current word in the ladder - must be string because we are deleting them from the vector,
        // so we must copy them
        std::string word { start };
    
        std::cout << word;
    
        while (word != target) {
            std::cout << "->";
    
            // find an element in the dictionary has hamming(el, word) == 1 (i.e. 'cord' and 'core').
            // this won't work if there's more than one match, because it will cause a loop.
            // This is also based on C++20's ranges, and it can be replaced with std::find_if
            const auto next_it { std::ranges::find_if(words, [word] (const auto el) { return hamming_distance(el, word) == 1; }) };
    
            // no match, it means the chain can't be completed
            if (next_it == std::end(words)) {
                std::cout << "X (no result)\n";
    
                return false;
            }
    
            // print the next element
            std::cout << *next_it;
          
            // set the next word as the newly found item
            word = *next_it;
    
            // remove it from the vector
            // while this is O(n), it's empirically as fast as using a more "optimized" container
            // due to how hecking fast vectors and memcpy are on modern CPUs
            words.erase(next_it); 
    
            ++len; // chain length counter
        }
    
        std::cout << "\nChain was " << len << " elements long\n";
    
        return true;
    }
    
    int main() {
        std::vector<std::string> words {
            "poon",
            "plee",
            "same",
            "poie",
            "plie",
            "poin",
            "plea",
        };
    
        const auto start { "toon"sv };
        const auto target { "plea"sv };
        
        const bool success { word_ladder(start, target, std::move(words)) };
       
        return success ? EXIT_SUCCESS : EXIT_FAILURE;
    } 
    
    toon->poon->poin->poie->plie->plee->plea
    Chain was 7 elements long