如何解决一个小小的双链表拼图
免责声明
所以最初当我发布这个时,它是我的错误的前向列表,即使我打算将它作为一个双链表来做 - 这就是为什么有些回复与问题不匹配。
问题
我正在做一些编码,我必须在下面编码。乍一看,代码看起来没什么问题,但逻辑上存在缺陷。你能找到吗?
class Node {
int val;
Node *next,*prev;
public:
Node(int val,Node *prev,Node *next) {
this->val = val;
this->prev= prev;
this->next = next;
}
int get() {return val;}
Node* getNext() {return next;}
Node* getPrev() {return prev;}
};
int main() {
Node *n1,*n2,*n3;
n1 = new Node(1,NULL,n2);
n2 = new Node(2,n1,n3);
n3 = new Node(3,n2,NULL);
Node *next = n1;
while (next != NULL) {
cout << next->get() << endl;
next = next->getNext();
}
}
问题是指针 n1、n2、n3 只有在使用运算符 new 分配内存后才能获得正确的地址。这意味着这些指针的地址在 Node 类实例化时是不同的。例如。在
n2 = new Node(2,n3);
行中的 n3 将是一个错误的指针(因为内存尚未分配 jet 并且当前指向一些废话)。
问题
解决问题不是问题,但让我感到疑惑:
我的看法
对于第一个问题,我想到了最快的解决方案。我只是将属性 next 和 prev 指向指针并更改了代码,以便它将引用传递给构造函数。还必须更改 while 循环的语法以获取取消引用的值。
对于第二个问题,我们在回复中得到了一个可能的解决方案。我们可以简单地制作一个节点数组。这样我们就知道每个成员的确切地址,因为 n - 数组的第一个成员将有第一个成员的地址 + n - 1;
解决方法
例如。在行 n2 = new Node(2,n3); n3 将是一个坏指针
有一个简单的解决方案。固定初始化顺序,以便从没有依赖项的对象开始,并在它们的依赖项初始化后初始化对象。在这种情况下,“1”依赖于“2”而“2”依赖于“3”,因此:
n3 = new Node(3,nullptr);
n2 = new Node(2,n3);
n1 = new Node(1,n2);
可以提前分配内存吗?
当然。可以分配内存。如果你在做其他事情之前分配内存,那么你就是在做其他事情之前分配内存。
您可以使用数组一次性创建所有节点。您甚至不需要任何动态分配:
Node nodes[] {
{1,nodes + 1},{2,nodes + 2},{3,nullptr},};
Node* next = nodes;
附言
- 我建议不要使用裸指针。您的示例会泄漏内存。
- 不要在 C++ 中使用
NULL
。它已被nullptr
废弃。 - 无论出于何种原因,您都忘记初始化
prev
成员。
我认为改为使用指针到指针是一个非常非常糟糕的主意,而且会非常奇怪。
最简单的方法是反向构建树:
Node * n3 = new Node(3,nullptr);
Node * n2 = new Node(2,n3);
Node * n1 = new Node(1,n2);
这在创建 n2 之前使用 n2 消除了 n1。
但是,您仍然有问题。您在任何时候都不是在管理上一个。所以你可能想这样做:
Node(int val,Node *next) { 这-> val = val; this->next = next;
// Add these lines.
if (next != nullptr) {
next->prev = this;
}
}
另请注意,使用 NULL 来引用未初始化的指针是非常老式的 C。如果您要编写现代 C++,请改用 nullptr,如您在我的示例中所见。
我还做了一项与您不同的更改。我个人不喜欢这个代码:
Node *n1,*n2,*n3;
我不喜欢它有两个原因,至少在一些公司风格指南中都会提到这两个原因。首先,一些风格指南会告诉你每行只引用一个变量,而不是像你那样引用三个。而且,一些指南会警告您不要让指针未初始化。所以我打破了它,正如你在我上面的例子中看到的那样。
这最后一部分只是风格,但我无法告诉您由于其中一个或其他原因我追查的错误数量。例如,这可以隐藏:
Node *n1,n2,*n3;
根据您的字体大小、眼睛的锐度和月相,您可能看不到 n2 未声明为指针。现在,现代编译器可能会发现不好的用法,但仍然......此外,如果您同意所有变量在创建时都应初始化为合理的值,那么您的代码可能会变得冗长,并且很容易看不到您没有t 初始化一切。
,似乎您正在尝试创建一个双向链表。错误是您在构造函数中传递了 null 作为参数。如果您按以下顺序分配内存,则可以解决此问题:
Node *n3=new Node(3,NULL);
Node *n2=new Node(2,n3)
Node *n1=new Node(1,n2)
Node *next=n1
while(next!=NULL){
cout<<next->get();
next=next->getNext();
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。