我是第一个C ++课程的编程学生,最近我们介绍了链接列表,并且我们获得了一个实现简单编程的任务。我编写了除pop_back()
函数之外的所有函数,该函数用于返回指向需要在Node
中删除的Main()
的指针。在实际功能中不执行Node
删除。所以我的问题是:
您是否愿意帮助我指出pop_back()
功能正确的方向?另外,如果你发现其他任何我做错了,请告诉我。
此外,此链接列表仅用于处理字符串。在这种情况下,一个购物清单,所以一个字符串表示项目数量(1,2),一个字符串表示项目类型。 (牛奶,鸡蛋等)
下面我列出了我的列表&节点类实现,这样你就可以了解我到目前为止所做的工作。
Node.cpp
Node::Node(void)
{
descrip = " ";
quantity = " ";
previous = NULL;
next = NULL;
}
Node::Node(string q, string d)
{
descrip = d;
quantity = q;
previous = NULL;
next = NULL;
}
Node* Node::GetNext()
{
return next;
}
Node* Node::GetPrevious()
{
return previous;
}
void Node::SetNext(Node * setter)
{
next = setter;
}
void Node::SetPrevious(Node * setter)
{
previous = setter;
}
List.cpp
List::List(void)
{
first = NULL;
last = NULL;
numNodes = 0;
}
Node* List::GetFirst()
{
return first;
}
Node* List::GetLast()
{
return last;
}
void List::SetFirst(Node* setter)
{
first = setter;
}
void List::SetLast(Node* setter)
{
last = setter;
}
int List::GetNumNodes()
{
return numNodes;
}
void List::push_front(Node* item)
{
if (first == NULL)
{
first = item;
last = item;
}
else
{
Node* pFirst = first;
item->SetNext(pFirst);
first = item;
numNodes++;
}
}
void List::push_back(Node * item)
{
if (last == NULL)
{
first = item;
last = item;
}
else
{
last->SetNext(item);
last = item;
numNodes++;
}
}
Node* List::pop_front()
{
Node* temp = first;
first = first->GetNext();
if (first == NULL)
{
temp = first->GetNext();
first = p;
}
if (first == NULL)
{
last = NULL;
}
if (numNodes > 0)
{
numNodes--;
}
return temp;
}
Node* List::pop_back() // this whole function may be wrong, this is just my attempt at it
{
Node* temp;
temp = first;
while((temp->GetNext()) != NULL)
// im stuck here
}
答案 0 :(得分:4)
一些指示:
0x1243bfa3
0x45afc56e
0xdeadbeef
更多指示:
您应该更喜欢在初始化列表中初始化类成员,而不是在构造函数的主体中初始化。
在C ++中,与C89不同,我们声明并定义一个没有参数的函数void f();
,而不是void f(void);
。
在C ++中,我们通常使用0
重置指针,而不是NULL
。
请参阅下文,了解我在代码中的含义。
好的C ++代码会尝试利用RAII。这意味着在大多数情况下避免使用原始指针。在这种情况下,普通的旧std::auto_ptr<>
将完全替代原始Node*
指针。但是,我认为这里的部分练习是指针算术,所以我只是留下这个作为旁注。
如果您附加了类声明,它对我们很有用。我假设所有那些访问者和变异者GetFirst()
和SetFirst()
等都存在,因为它们是公开的。这是个坏主意。首先,它们暴露私有指针,这会破坏访问者的整个点。其次,他们没有做任何特别的事情,所以他们只是额外的代码 - 这意味着额外的错误空间。这让我想到了下一点。
你的变异者是不正确的。您盲目地为私有成员指针指定一个新值,而不删除之前的内容。这是内存泄漏。
当列表为空时,曾试过pop_front()
吗?
最后,8是一个圆数,是时候我们得到了手头的问题。 pop_back()
。我的问题是,如果您如此精心维护指向列表最后一个节点的指针,为什么要一直遍历列表?实际上,如果您不打扰维护指向列表末尾的指针,那么您必须遍历到最后一个节点才能弹出它。为此你正朝着正确的方向前进。除此之外......
当您通过指针访问成员时,如first->GetNext()
,总是确保first
不是空指针 - 或者在函数中指出您认为指针不为空的文档注释。
这些应该可以帮到你。
代码中的第1,2和3点:
Node::Node()
: descrip(" "), quantity(" "), previous(0), next(0)
{
}
答案 1 :(得分:1)
所以,如果我理解这一点你只想运行你的链表,直到你到达链表中的最后一个节点并返回它的指针? 我非常肯定你有什么会做的,除了
Node* List::pop_back() // this whole function may be wrong, this is just my attempt at it
{
Node* temp;
temp = first;
while(temp->GetNext() != NULL)
{
temp = temp->GetNext();
}
return temp;
}
因此,如果我正确阅读它,它将不断循环,直到它到达后面的行中没有的节点,然后返回它。
答案 2 :(得分:0)
我喜欢之前的海报答案,但有一件事你可能要记住,如果你有一个空列表。然后你的第一个指针将等于NULL,你将尝试基本上调用NULL-&gt; GetNext()和Seg Fault。我认为你可以稍微编辑上面的代码,但仍然可以这样工作:
Node* List::pop_back()
{
Node* temp;
temp = first;
while(temp != NULL && temp->GetNext() != NULL)
{
temp = temp->GetNext();
}
return temp;
}
如果列表中没有任何内容并且仍能正常工作,则此函数将返回NULL。
答案 3 :(得分:-1)
如果您还发布了课程声明,肯定会帮助我。我无法保证以下内容是正确的,但对我来说是有意义的
Node* List::pop_back()
{
Node *temp = NULL;
if(numNodes == 1)
{
temp = first;
// setting the list pointers to NULL
first = NULL;
// setting the list pointers to NULL
last = NULL;
//You should also probably remove the links from your node
//to the next and previous nodes but since you didn't specify
//this it is up to you
numNodes--;
}
else if(numNodes > 1) //more than one element
{
//the pointer you want to return
temp = last;
//For clarity I am creating another variable here
Node *newLast = temp->GetPrevious();
//Setting the new last node to point at nothing so now temp
//is "disconnected from the list"
newLast->next = NULL;
//the last pointer of the list is now pointing at the new last node
last = newLast;
//You should also probably remove the links from your node
//to the next and previous nodes but since you didn't specify this it is up to you
numNodes--; //decrement the counter
}
return temp;
}