我有一个名为StringList.h的头文件,其中包含以下内容:
#include <string>
using namespace std;
class StringList;
class StringListNode
{
friend class StringList;
private:
StringListNode * pPrev;
string data;
StringListNode * pNext;
};
class StringList
{
public:
StringList();
~StringList();
void addToBottom(string s);
void addToTop(string s);
void remove(string s);
string print();
void clear();
bool isEmpty() {return (pTop==NULL);}
private:
StringListNode * pTop;
StringListNode * pBottom;
};
我的StringList.cpp文件将包含我所有函数的定义。 到目前为止,我想出了如何添加addotot和addtoBottom工作
addToTop:
if(isEmpty())
{
StringListNode * pNewNode;
pNewNode = new StringListNode;
(*pNewNode).data = s;
pTop=pNewNode;
pBottom=pNewNode;
(*pNewNode).pPrev = NULL;
(*pNewNode).pNext = NULL;
}
else //it's not empty
{
StringListNode * pNewNode;
pNewNode = new StringListNode;
(*pNewNode).data = s;
(*pNewNode).pNext = pTop;
(*pTop).pPrev = pNewNode;
(*pNewNode).pPrev =NULL;
pTop=pNewNode;
}
addToBottom基本相同,但在else语句中用pBottom替换pTop。 现在,我陷入困境的地方正在移除。我想通过每个点头,直到它找到*数据中的字符串并删除它。但是,我真的不知道如何使我想要删除的节点的前一个指针指向下一个节点的pNext。有什么建议吗?
打印():
string StringList::print()
{
string result;
StringListNode * pCurrent;
pCurrent=pTop;
while(pCurrent!=NULL)
{
result+=(*pCurrent).data+"\n";
pCurrent=(*pCurrent).pNext;
}
return result;
}
答案 0 :(得分:0)
假设您在双向链接列表中有三个节点,并且您想删除由curr
标识的中间节点:
curr ----------------------+
|
v
+--------+ +--------+ +--------+
...----| pPrev |<------| pPrev |<------| pPrev |<---...
| Node 1 | | Node 2 | | Node 3 |
...--->| pNext |------>| pNext |------>| pNext |----...
+--------+ +--------+ +--------+
两个重新连接操作是:
curr->pPrev->pNext = curr->pNext; // Previous node's next points to curr's next
curr->pNext->pPrev = curr->pPrev; // Next node's previous points to curr's previous
您现在可以以任何合适的方式处置curr
。唯一的诀窍是处理终结案件;删除列表开头或结尾的节点或列表中唯一的节点时会发生什么。什么是合适的取决于您创建列表的方式。你有空指针,圆形列表,还是......
鉴于您使用空指针来标记列表的末尾,您必须在删除时检查空指针。
if (curr->pPrev != 0)
curr->pPrev->pNext = curr->pNext;
if (curr->pNext != 0)
curr->pNext->pPrev = curr->pPrev;
您还必须处理curr
作为列表的头部,调整头部(pTop
)或将其作为列表的尾部,调整尾部(pBottom
)。您还必须处理curr
作为列表中唯一的节点。
表面正常工作的代码......未通过valgrind
验证。但是,重复使用toString()
成员函数(néeprint()
)表明列表结构正常。没有关于没有泄漏的承诺。
#include <string>
using namespace std;
class StringList
{
private:
struct StringListNode
{
StringListNode *pPrev;
string data;
StringListNode *pNext;
};
public:
StringList() : pTop(0), pBottom(0) {}
~StringList();
void addToTop(const string &s);
void remove(const string &s);
string toString();
bool isEmpty() { return (pTop == NULL); }
private:
StringListNode *pTop;
StringListNode *pBottom;
StringListNode *find(const string &s);
};
string StringList::toString()
{
string result;
StringListNode *pCurrent = pTop;
while (pCurrent != NULL)
{
result += pCurrent->data + "\n";
pCurrent = pCurrent->pNext;
}
return result;
}
StringList::StringListNode *StringList::find(const string &s)
{
StringListNode *sp = pTop;
while (sp != 0 && sp->data != s)
sp = sp->pNext;
return sp;
}
void StringList::addToTop(const string &s)
{
if (isEmpty())
{
StringListNode * pNewNode = new StringListNode;
pNewNode->data = s;
pNewNode->pPrev = NULL;
pNewNode->pNext = NULL;
pTop = pNewNode;
pBottom = pNewNode;
}
else
{
StringListNode * pNewNode;
pNewNode = new StringListNode;
pNewNode->data = s;
pNewNode->pNext = pTop;
pNewNode->pPrev = NULL;
pTop->pPrev = pNewNode;
pTop = pNewNode;
}
}
void StringList::remove(const string &s)
{
StringListNode *curr = this->find(s);
if (curr == 0)
return;
if (curr->pPrev != 0)
curr->pPrev->pNext = curr->pNext;
if (curr->pNext != 0)
curr->pNext->pPrev = curr->pPrev;
if (pTop == curr)
pTop = curr->pNext;
if (pBottom == curr)
pBottom = curr->pPrev;
}
StringList::~StringList()
{
StringListNode *next;
for (StringListNode *sp = pTop; sp != 0; sp = next)
{
next = sp->pNext;
delete sp;
}
}
#include <iostream>
int main()
{
StringList s;
s.addToTop("abc");
std::cout << "After add abc: " << s.toString();
s.addToTop("def");
std::cout << "After add def: " << s.toString();
s.addToTop("ghi");
std::cout << "After add ghi: " << s.toString();
s.addToTop("jkl");
std::cout << "After add jkl: " << s.toString();
s.remove("def");
std::cout << "After del def: " << s.toString();
s.remove("ghi");
std::cout << "After del ghi: " << s.toString();
s.remove("abc");
std::cout << "After del abc: " << s.toString();
s.remove("jkl");
std::cout << "After del jkl: " << s.toString();
return 0;
}