簡體   English   中英

如何在n路樹上生孩子?

[英]How to get a child in an n-way tree?

我有一個使用std :: vector實現的n路樹。 Node類僅包含指向根元素的指針,而Link類具有指向其自身的std :: vector指針。 創建鏈接時,我要為每個鏈接命名,但是當我嘗試使用鏈接名稱在此樹中定位節點時,卻遇到了分段錯誤。 我也意識到我的函數GetLink()不執行任何錯誤檢查,我嘗試了幾件事,但是它們沒有用,因此,如果可能的話,在這種情況下如何實現的任何建議將不勝感激。 這是我的代碼:

// in node.h
class Node {
public:
 // constructors
 // fuctions
private:
 Link *root;
};

// in link.h
class Link {
public:
//EDIT: added vector initialization in the constructor
 Link() : my_links(0) { }
 // some functions
 // EDIT: example of making the tree
 bool Load(token) {
 // parsing code based on token
   else if (strcmp (temp, "link") == 0)
   {
        Link* lnk = new Link ();
        lnk->Load (token);
        lnk->Init ();
        AddChild (lnk);
        lnk->m_parent = this;
   }
    // some more parsing code
 }
 void Link::AddChild (Link* pChild)
 {
   my_links.push_back(pChild);
 }

 Link* Link::GetLink(char* str)  // this is the function that is the problem.
 {
   if (strcmp(name, str) == 0)
   {
     return this;
   }

   for (int i=0; i < (int) my_links.size(); i++)
   {
    //Edit: added check for NULL ptr
     if (my_links[i] == NULL)
     {
        fprintf (stderr, "\n\t Couldn't find link\n\n");
        break;
     } 
     //Edit: typo corrected
     return my_links[i]->GetLink(str);
   }
 }

private:
 char name[256];
 Link* m_parent;
 std::vector<Link*> my_links;
};

// in main.cpp
static Node* node;
static Link* link;
main()
{
  char *str = "link_3";
  link = node->GetLink(str);
  printf("\n found link: %s", link->GetName());
  retrun 0;
}

編輯:將早期的代碼重寫為MCVE

#include <cstdio>
#include <vector>
#include <cstring>

class Link {
public:
//EDIT: added vector initialization in the constructor
 Link() : my_links(0)
 {
   m_parent = NULL;
 }

 void SetParent(Link* pParent)
 {
   m_parent = pParent;
 }

 // EDIT: example of making the tree
 bool Load(char *str)
 {
        unsigned int len;
        Link* lnk = new Link ();
        len = strlen(str);
        strcpy(name, str);
        lnk->SetParent(this);
        AddChild (lnk);
        return true;
 }

 void AddChild (Link* pChild)
 {
   my_links.push_back(pChild);
 }

 Link* GetLink(char* str)  // this is the function that is the problem.
 {
   if (strcmp(name, str) == 0)
   {
     return this;
   }

   for (int i=0; i < (int) my_links.size(); i++)
   {
    //Edit: added check for NULL ptr
     if (my_links[i] == NULL)
     {
        fprintf (stderr, "\n\t Couldn't find link\n\n");
        break;
     }
     //Edit: typo corrected
     return my_links[i]->GetLink(str);
   }
   fprintf(stderr, "\n\t Cannot get link\n\n");
   return 0;
 }

 char* GetName()
 {
   return name;
 }

private:
 char name[256];
 Link* m_parent;
 std::vector<Link*> my_links;
};


class Node {
public:
 Node()
 {
    root = NULL;
 }

 bool Load (char *str)
 {
    unsigned int len;
    root = new Link();  // here is where the error occurs
    len = strlen(str);
    strcpy(name, str);
    return true;
 }

 void AddChild (char *str)
 {
   root->Load(str);
 }

 Link* GetRoot()
 {
   return root;
 }

private:
 char name[256];
 Link *root;
};

static Node* node;
static Link* lnk;
int main()
{
  node->Load((char*)"I am root");
  node->AddChild((char*)"I am child 1");
  node->AddChild((char*)"I am child 2");
  node->AddChild((char*)"I am child 3");
  char *str = (char*)"I am child 2";
  lnk = node->GetRoot()->GetLink(str);
  printf("\n found link: %s", lnk->GetName());
  return 0;
}

我現在在VS2010的第77行上得到的錯誤是Node類中的“ root = new Link()”,Load()函數為:

Unhandled exception at 0x012e1bbe in nWayTree.exe: 0xC0000005: Access violation writing location 0x00000100.

在MCVE中收到錯誤的原因是,您從未實例化node ,因此, node->Load((char*)"I am root"); 取消引用未初始化的指針,導致未定義的行為。 實際上,當您的程序試圖寫入希望“ root”成員變量存在的內存位置時,您會遇到訪問沖突。 您可以通過編寫來解決此問題

static Node* node = new Node();

但是,即使更正了此錯誤,您的MCVE仍然存在語義錯誤。 每次調用node->AddChild ,都不會添加另一個子節點,而是重命名節點,並為node的root成員變量分配一個新的默認構造鏈接(無名稱)。 同樣,您的GetLink()函數不會遞歸地在所有子節點上調用GetLink()(如果有的話),而只會在第一個子節點上調用GetLink(),然后無條件返回結果(循環在一次執行)。

另外,Node,Link和root之間的區別對我也不是很清楚。 這是我假設要實現的目標,並且要盡可能少地增加c ++(與您的示例相比):

#include <cstdio>
#include <vector>
#include <cstring>

class Node {
private:
    char m_name[256];
    Node* m_parent;
    std::vector<Node*> my_links;
public:
    //EDIT: added vector initialization in the constructor
    Node(const char* name, Node* parent=nullptr) : m_parent(parent), my_links() {
        strcpy(m_name, name);
    }

    void AddChild(const char* childname) {
        my_links.push_back(new Node(childname,this));
    }

    Node* GetNode(const char* str)  {
        if (strcmp(m_name, str) == 0)   {
            return this;
        }
        for (size_t i = 0; i < my_links.size(); i++) 
        { 
            Node* t = my_links[i]->GetNode(str); 
            if (t != NULL) return t; 
        } 
        return NULL; 

    }

    char* GetName() {
        return m_name;
    }
};

Node root((const char*)"I am root");

int main()
{
    root.AddChild("I am child 1");
    root.AddChild("I am child 2");
    root.AddChild("I am child 3");  
    const char *str1 = "I am child 2";
    const char *str2 = "I am child 1 of child 2 of root";
    root.GetNode(str1)->AddChild(str2);
    Node* node = root.GetNode(str2);
    if (node == NULL) {
        printf("Link not found");
    } else
    {
        printf("\n found link: %s", node->GetName());
    }
}

這是“現代c ++樣式”版本(不聲稱它是特別好的版本):

編輯:我剛剛意識到您正在使用VS2010,它將無法編譯以下示例,因為它使用了某些c ++ 11和c ++ 14(當前的c ++標准)功能。 但是,您可以使用VS2013的免費版本來構建它,並且應該能夠使用g ++和clang ++的任何最新版本來構建它(不過,您必須添加標記'-std = c ++ 14'或類似標記)。

#include <iostream>
#include <vector>
#include <string>
#include <memory>

using namespace std;

class Node {
private:
    string m_name;
    Node* m_parent;
    vector<unique_ptr<Node>> my_links;

public: 
    Node(const string& name, Node* parent = nullptr) : 
        m_name(name),
        m_parent(parent), 
        my_links()
    {}

    void AddChild(const string& childname) {
        my_links.push_back(make_unique<Node>(childname, this));
    }

    Node* GetNode(const string& str)  {
        if (m_name == str)  {
            return this;
        } 
        for (auto& e:my_links) 
        { 
            Node* t = e->GetNode(str);
            if (t != nullptr) return t; 
        } 
        return nullptr;         
    }

    string GetName()    {
        return m_name;
    }
};

Node root("I am root");

int main()
{
    root.AddChild("I am child 1");
    root.AddChild("I am child 2");
    root.AddChild("I am child 3");
    string str1("I am child 2");
    string str2("I am child 1 of child 2 of root");
    root.GetNode(str1)->AddChild(str2);
    Node* node = root.GetNode(str2);
    if (node == nullptr) {
        cout <<"Link not found";
    } else  {
        cout << "found link: "<< node->GetName();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM