这是一个DLinkedList实现,使用addFront()添加了int类型的元素,但是没有使用front()检索它。没有显示错误。不知道为什么?这是完整的实施。代码在xCode4.5上运行。
int main(int argc, const char * argv[])
{
DLinkedList listOne;
if(listOne.empty()){
cout<<"Empty";
}
const int num=23;
listOne.addFront(num);
//Here 0 is returned from front(), while it should be 23;
cout<<listOne.front()<<endl;
return 0;
}
//Node Defination
class DNode { // doubly linked list node
private:
int elem; // node element value
DNode* prev; // previous node in list
DNode* next; // next node in list
friend class DLinkedList; // allow DLinkedList access
};
class DLinkedList { // doubly linked list
public:
DLinkedList(); // constructor
~DLinkedList(); // destructor
bool empty() const; // is list empty?
const int front() const; // get front element
const int back() const; // get back element
void addFront(const int e); // add to front of list
void addBack(const int e); // add to back of list
void removeFront(); // remove from front
void removeBack(); // remove from back
private: // local type definitions
DNode* header; // list sentinels
DNode* trailer;
protected: // local utilities
void add(DNode* v, const int e); // insert new node before v
void remove(DNode* v); // remove node v
};
void listReverse(DLinkedList& L) { // reverse a list
DLinkedList T; // temporary list
while (!L.empty()) { // reverse L into T
int s = L.front(); L.removeFront();
T.addFront(s);
}
while (!T.empty()) { // copy T back to L
int s = T.front(); T.removeFront();
L.addBack(s);
}
}
void DLinkedList::remove(DNode* v) { // remove node v
DNode* u = v->prev; // predecessor
DNode* w = v->next; // successor
u->next = w; // unlink v from list
w->prev = u;
delete v;
}
void DLinkedList::removeFront() // remove from font
{ remove(header->next); }
void DLinkedList::removeBack() // remove from back
{ remove(trailer->prev); }
// insert new node before v
void DLinkedList::add(DNode* v, const int e) {
DNode* u = new DNode; u->elem = e; // create a new node for e
std::cout<<u->elem<<std::endl;
u->next = v; // link u in between v
u->prev = v->prev; // ...and v->prev
v->prev->next = v->prev = u;
}
void DLinkedList::addFront(const int e) // add to front of list
{
add(header->next, e);
}
void DLinkedList::addBack(const int e) // add to back of list
{ add(trailer, e); }
DLinkedList::~DLinkedList() { // destructor
while (!empty()) removeFront(); // remove all but sentinels
delete header; // remove the sentinels
delete trailer;
}
DLinkedList::DLinkedList() { // constructor
header = new DNode; // create sentinels
trailer = new DNode;
header->next = trailer; // have them point to each other
trailer->prev = header;
std::cout<<"DLinkedListConstructor"<<std::endl;
}
bool DLinkedList::empty() const // is list empty?
{ return (header->next == trailer); }
const int DLinkedList::front() const // get front element
{ return header->next->elem; }
const int DLinkedList::back() const // get back element
{ return trailer->prev->elem; }
答案 0 :(得分:3)
问题在于您的add
功能:
// insert new node before v
void DLinkedList::add(DNode* v, const int e) {
DNode* u = new DNode; u->elem = e; // create a new node for e
std::cout<<u->elem<<std::endl;
u->next = v; // link u in between v
u->prev = v->prev; // ...and v->prev
v->prev->next = v->prev = u;
}
让我们来完成。您从以下情况开始(我称之为v->prev
指向p
的节点):
┌───────────┐
│ ▼
p ◀──────── v
u
然后,您将u->next
设置为v
:
┌───────────┐
│ ▼
p ◀──────── v
▲
u─────┘
然后u->prev
改为v->prev
:
┌───────────┐
│ ▼
p ◀──────── v
▲ ▲
└─────u─────┘
下一行是问题所在。首先,它将u
分配给v->prev
:
┌───────────┐
│ ▼
p ┌──── v
▲ ▼ ▲
└─────u─────┘
然后它为v->prev->next
分配相同的指针。但v->prev
现在是u
,因此您只需将u->next
设置为v
即可。所以没有变化。
现在当你尝试获取前面的元素时,你只是得到元素v
,这是你的前哨节点。
您需要单独执行这两项任务:
v->prev->next = u;
v->prev = u;
答案 1 :(得分:2)
首先,您没有初始化所有节点的prev
和next
指针。构造列表时,列表的构造函数会执行:
header = new DNode; // create sentinels
trailer = new DNode;
header->next = trailer; // have them point to each other
trailer->prev = header;
这意味着header->prev
和trailer->next
未初始化。这些指针不会自动初始化为NULL
,所以要小心。
但是你所观察到的根本原因是你的add_front()
函数中,你正在调用一个add()
函数,最终会这样做:
// Replacing v with header->next, which is the actual argument of the call
...
u->next = header->next; // u->next = trailer
u->prev = header->next->prev; // u->prev = trailer->prev; // Uninitialized!
header->next->prev = u; // trailer->prev = u;
header->next->prev->next = u; // u->next = u
由于最后一个陈述,这显然是错误的,因为你永远不会分配header->next = u
。
nullptr
。
答案 2 :(得分:1)
代码在Windows中的Mingw Compiler上运行得很好,使用代码块给出了23而不是0。 但是,我建议进行以下更改,因为有些编译器会从右到左分配值,堆栈事物......
void DLinkedList::add(DNode* v, const int e) {
DNode* u = new DNode; u->elem = e; // create a new node for e
std::cout<<u->elem<<std::endl;
u->next = v; // link u in between v
u->prev = v->prev; // ...and v->prev
v->prev->next = u; // do this first......
v->prev = u; // then this.
}