我有一个名为StringList的类,而不是具有多个管理和操作链接字符串列表的函数。我有一个添加到列表顶部的AddtoTop,AddtoBottom,一个名为add的函数,它添加一个字符串,但按字母顺序排列,一个清除函数,一个查找函数,打印和删除函数。我写过每一个函数,但是我有一个主要问题。当我使用“AddtoTop”和“AddtoBottom”时,我在链表中添加一个字符串。当我要求删除仅使用这两个函数放置的字符串时,我的删除功能有效。当我尝试删除使用“添加”功能添加的单词时,我的程序崩溃了。函数“remove”(如下所示)可以删除使用“AddtoBottom”和“AddtoTop”函数添加的字符串,但不能删除使用“add”添加的字符串任何人都可以帮我找出原因吗?我试图以不同的方式重写它,但我卡住了。这是我的职能:
StringList::StringList() //constructor
{
pTop=NULL;
pBottom=NULL;
}
StringList::~StringList() //destructor
{
StringListNode *next;
for (StringListNode *sp = pTop; sp != 0; sp = next)
{
next = sp->pNext;
delete sp;
}
}
void StringList::add(string s) //adds and places in alphabetical order
{
if(pTop)
{
if( s < pTop->data )
{
StringListNode *A=new StringListNode;
A->data = s;
A->pNext = pTop;
pTop = A; // new top
return;
}
// go further into list
StringListNode *iter = pTop;
while( iter->pNext )
{
if( iter->pNext->data < s )
iter = iter->pNext;
else
break;
}
StringListNode *in=new StringListNode; //actuallly inserts node
in->data = s;
in->pNext = iter->pNext;
iter->pNext = in;
}
else// new item
{
pTop = new StringListNode;
pTop->data = s;
pTop->pNext = NULL;
}
}
StringList::StringListNode *StringList::find(const string &s) //basic search function
{
StringListNode *sp = pTop; // Search
while (sp != 0 && sp->data != s)
sp = sp->pNext;
return sp;
}
void StringList::addToTop(string s) //add to top of nodes
{
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;
}
}
void StringList::addToBottom(string s) // add to bottom
{
if(isEmpty())
{
StringListNode * pNewNode;
pNewNode = new StringListNode;
(*pNewNode).data = s;
pTop=pNewNode;
pBottom=pNewNode;
(*pNewNode).pPrev = NULL;
(*pNewNode).pNext = NULL;
}
else
{
StringListNode * pNewNode;
pNewNode = new StringListNode;
(*pNewNode).data = s;
(*pBottom).pNext = pNewNode;
(*pNewNode).pPrev = pBottom;
(*pNewNode).pNext =NULL;
pBottom=pNewNode;
}
}
string StringList::print() //prints strings in linked list
{
string result;
StringListNode * pCurrent;
pCurrent=pTop;
while(pCurrent!=NULL)
{
result+=(*pCurrent).data+"\n";
pCurrent=(*pCurrent).pNext;
}
return result;
}
void StringList::clear() //clears everything
{
pTop = NULL;
pBottom = NULL;
}
void StringList::remove(string s) //removes a string
{
StringListNode *curr = this->find(s);
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;
}
答案 0 :(得分:0)
尝试这样的事情:
void StringList::add(string s) //adds and places in alphabetical order
{
if(pTop)
{
StringListNode *iter = pTop;
while (iter && s > iter->data)
iter = iter->pNext;
if (iter)
{
// insert before
StringListNode *A=new StringListNode;
A->data = s;
A->pNext = iter;
A->pPrev = iter->pPrev;
if (iter->pPrev)
iter->pPrev->pNext = A;
else
pTop = A;
iter->pPrev = A;
return;
}
}
// add to bottom
addToBottom(s);
}
请注意,您最好使用std::set
(或std::multiset
),而不是滚动自己的列表代码,因为这会使字符串自动排序,并且查找和随机插入通常在对数时间而不是线性。
答案 1 :(得分:0)
编写的add()
代码的一个主要问题是它没有设置pPrev
指针(但应该)。绘制一个类似于我在回答“如何删除”问题时使用的图表,并查看在添加新节点时需要进行的分配。
还值得思考'如何检查数据结构是否合理'?例如,在列表中间的每个节点curr
,您应该能够断言:
assert(curr->pPrev->pNext == curr);
assert(curr->pNext->pPrev == curr);
调整结束指针为空,您可以写:
assert(curr->pPrev == 0 || curr->pPrev->pNext == curr);
assert(curr->pNext == 0 || curr->pNext->pPrev == curr);
您的add()
代码无法确保维护这些不变量。你也遇到了问题;如果列表由addToTop()
或addToBottom()
维护,那么使用add()
将无法可靠地运行,因为列表不能保证按排序顺序。
此外,正如我在回答您之前的问题时所展示的(但没有具体讨论),您应该将字符串传递为const string &s
,而不是使用string s
。一般来说,它对代码的效率有很大的影响。