我正在研究C ++中的链表实现。我正在取得进展,但我无法使插入功能和删除功能正常工作。下面是C ++头文件中的列表对象:
#ifndef linkList_H
#define linkList_h
//
// Create an object to represent a Node in the linked list object
// (For now, the objects to be put in the list will be integers)
//
struct Node
{
Node() : sentinel(0) {}
int number;
Node* next;
Node* prev;
Node* sentinel;
};
//
// Create an object to keep track of all parts in the list
//
class List
{
public:
//
// Contstructor intializes all member data
//
List() : m_listSize(0), m_listHead(0) {}
//
// methods to return size of list and list head
//
Node* getListHead() const { return m_listHead; }
unsigned getListSize() const { return m_listSize; }
//
// method for adding and inserting a new node to the linked list,
// retrieving and deleting a specified node in the list
//
void addNode(int num);
void insertNode(Node* current);
void deleteNode(Node* current);
Node* retrieveNode(unsigned position);
private:
//
// member data consists of an unsigned integer representing
// the list size and a pointer to a Node object representing head
//
Node* m_listHead;
unsigned m_listSize;
};
#endif
这是实现(.cpp)文件:
#include "linkList.h"
#include <iostream>
using namespace std;
//
// Adds a new node to the linked list
//
void List::addNode(int num)
{
Node *newNode = new Node;
newNode->number = num;
newNode->next = m_listHead;
m_listHead = newNode;
++m_listSize;
}
//
// NOTWORKING: Inserts a node which has already been set to front
// of the list
//
void List::insertNode(Node* current)
{
// check to see if current node already at
// head of list
if(current == m_listHead)
return;
current->next = m_listHead;
if(m_listHead != 0)
m_listHead->prev = current;
m_listHead = current;
current->prev = 0;
}
//
// NOTWORKING: Deletes a node from a specified position in linked list
//
void List::deleteNode(Node* current)
{
current->prev->next = current->next;
current->next->prev = current->prev;
}
//
// Retrieves a specified node from the list
//
Node* List::retrieveNode(unsigned position)
{
if(position > (m_listSize-1) || position < 0)
{
cout << "Can't access node; out of list bounds";
cout << endl;
cout << endl;
exit(EXIT_FAILURE);
}
Node* current = m_listHead;
unsigned pos = 0;
while(current != 0 && pos != position)
{
current = current->next;
++pos;
}
return current;
}
在客户端C ++代码中运行一个简短的测试程序后,结果输出如下:
Number of nodes: 10
Elements in each node:
9 8 7 6 5 4 3 2 1 0
Insertion of node 5 at the list head:
4 9 8 7 6 5 4 9 8 7
Deletion of node 5 from the linked list
如您所见,插入不仅仅是将节点5移动到列表头部,而是覆盖从第三个位置开始的其他节点。我试图实现的伪代码来自MIT算法书:
LIST-INSERT(L, x)
next[x] <- head[L]
if head[L] != NIL
then prev[head[L]] <- x
head[L] <- x
prev[x] <- NIL
此外,删除实现只是在调用方法时崩溃。不确定为什么;但这里是相应的伪代码:
LIST-DELET'
next[prev[x]] <- next[x]
prev[next[x]] <- prev[x]
老实说,我不确定前一个,下一个和一些哨兵指针是如何在内存中工作的。我知道他们应该在实际意义上做什么,但看看调试器看起来这些指针在删除的情况下并没有指向任何东西:
(*current).prev 0xcdcdcdcd {number=??? next=??? prev=??? ...} Node *
number CXX0030: Error: expression cannot be evaluated
next CXX0030: Error: expression cannot be evaluated
prev CXX0030: Error: expression cannot be evaluated
sentinel CXX0030: Error: expression cannot be evaluated
非常感谢任何帮助!!
答案 0 :(得分:0)
addNode()
出现错误。在你修复之前,你不能指望insertNode工作。
另外,我认为你的设计非常愚蠢。例如,一个名为“insertNode”的方法应该在任意位置插入一个新项,但是你的方法insertNode做了一个非常不同的事情,所以你应该重命名它。还应重命名addNode。同样,当glowcoder写道,为什么有那么多的哨兵?我担心你的班级设计整体上很糟糕。
实际错误是您忘记设置旧头的prev
属性。它应该指向新的头脑。
void List::addNode(int num)
{
Node *newNode = new Node;
newNode->number = num;
newNode->next = m_listHead;
if(m_listHead) m_listHead->prev = newNode;
m_listHead = newNode;
++m_listSize;
}
同样,deleteNode()
还有另一个错误。从列表中删除最后一项时它不起作用。
void List::deleteNode(Node* current)
{
m_listSize--;
if(current == m_listHead) m_listHead = current->next;
if(current->prev) current->prev->next = current->next;
if(current->next) current->next->prev = current->prev;
}
现在你可以修复你所谓的insertNode:
void List::insertNode(Node* current)
{
int value = current->number;
deleteNode(current);
addNode(value);
}
请注意,我在这里写了一切,没有在C ++编译器中编译和测试。也许有一些错误,但我希望它至少可以帮助你一点点。
答案 1 :(得分:0)
在deleteNode中,您不处理current-&gt; next和/或current-&gt; prev为null的情况。此外,如果当前恰好是头部,则不会更新列表头。
你应该这样做:
node* next=current->next;
node* prev=current->prev;
if (next!=null) next->prev=prev;
if (prev!=null) prev->next=next;
if (m_listhead==current) m_list_head=next;
(警告:我实际上没有测试过上面的代码 - 但我认为这足以说明我的想法)
我不确定您的InsertNode方法到底是什么,所以我无法在那里提供任何帮助。
答案 2 :(得分:0)
行。
正如@Al Kepp指出的那样,你的“添加节点”是错误的。看看Al的代码并修复它。
您正在执行的“插入”似乎不是正常的列表插入。相反,它似乎是一种“向前迈进”的行动。
尽管如此,您需要先将节点从列表中的当前位置删除,然后再将其添加到列表的开头。
<强>更新强>
我认为你误解了插入应该如何工作。它应该插入一个新节点,而不是列表中已有的节点。
请参阅下面的一个简单示例。
#include <iostream>
// List Node Object
//
struct Node
{
Node(int n=0);
int nData;
Node* pPrev;
Node* pNext;
};
Node::Node(int n)
: nData(n)
, pPrev(NULL)
, pNext(NULL)
{
}
//
// List object
//
class CList
{
public:
//
// Contstructor
//
CList();
//
// methods to inspect list
//
Node* Head() const;
unsigned Size() const;
Node* Get(unsigned nPos) const;
void Print(std::ostream &os=std::cout) const;
//
// methods to modify list
//
void Insert(int nData);
void Insert(Node *pNew);
void Delete(unsigned nPos);
void Delete(Node *pDel);
private:
//
// Internal data
//
Node* m_pHead;
unsigned m_nSize;
};
/////////////////////////////////////////////////////////////////////////////////
CList::CList()
: m_pHead(NULL)
, m_nSize(0)
{
}
Node *CList::Head() const
{
return m_pHead;
}
unsigned CList::Size() const
{
return m_nSize;
}
void CList::Insert(int nData)
{
Insert(new Node(nData));
}
void CList::Insert(Node *pNew)
{
pNew->pNext = m_pHead;
if (m_pHead)
m_pHead->pPrev = pNew;
pNew->pPrev = NULL;
m_pHead = pNew;
++m_nSize;
}
void CList::Delete(unsigned nPos)
{
Delete(Get(nPos));
}
void CList::Delete(Node *pDel)
{
if (pDel == m_pHead)
{
// delete first
m_pHead = pDel->pNext;
if (m_pHead)
m_pHead->pPrev = NULL;
}
else
{
// delete subsequent
pDel->pPrev->pNext = pDel->pNext;
if (pDel->pNext)
pDel->pNext->pPrev = pDel->pPrev;
}
delete pDel;
--m_nSize;
}
Node* CList::Get(unsigned nPos) const
{
unsigned nCount(0);
for (Node *p=m_pHead; p; p = p->pNext)
if (nCount++ == nPos)
return p;
throw std::out_of_range("No such node");
}
void CList::Print(std::ostream &os) const
{
const char szArrow[] = " --> ";
os << szArrow;
for (Node *p=m_pHead; p; p = p->pNext)
os << p->nData << szArrow;
os << "NIL\n";
}
int main()
{
CList l;
l.Print();
for (int i=0; i<10; i++)
l.Insert((i+1)*10);
l.Print();
l.Delete(3);
l.Delete(7);
l.Print();
try
{
l.Delete(33);
}
catch(std::exception &e)
{
std::cerr << "Failed to delete 33: " << e.what() << '\n';
}
l.Print();
return 0;
}