我的头指针应该是null,因为我不想要 当我制作我的链表时它有任何价值。
我知道你不能取消引用无效的东西, 但我只是想指出它是新事物的下一个节点。 谁能解释我怎么能指出头节点指针?
void dlist::push_front(int value) {
node *p = new node();
node *tempH = head();
tempH->next = p; //break
/***********************************************************
my head pointer is suposed to be null, because I don't want
it to have any value when I make my linked list.
I know that you can't dereference something that is null,
but I just want to point it's next node to something new.
can someone explane how I could point the head node pointer?
************************************************************/
p->value = value;
p->next = tempH->next;
p->prev = tempH;
p->next->prev = p;
p->prev->next = p;
}
#pragma once
#include <ostream>
class dlist {
public:
dlist() {}
// Implement the destructor, to delete all the nodes
//~dlist();
struct node {
int value;
node* next;
node* prev;
};
node* head() const { return _head; }
node* tail() const { return _tail; }
void push_front(int value);
private:
node* _head = nullptr;
node* _tail = nullptr;
};
答案 0 :(得分:0)
在列表构造函数中,只需将头指针设置为null。
dlist::dlist() {
_head = nullptr;
}
此外,如果您最终删除列表中的最后一项,则还需要生成_head = nullptr;
在解除引用之前,请务必检查磁头是否为空。
if(_head == nullptr){
_head = new node(...);
}
如果您要添加到未初始化的列表,您的插入功能将负责将第一个节点分配给头部。
如果需要对列表进行排序,则需要考虑新节点应位于头节点之前的头部更改。
答案 1 :(得分:0)
这里最实用的解决方案是只使用前哨节点作为头部和尾部。或者,只有一个前哨节点,它代表两者。前哨节点的元素可以保持未初始化,您只需要那些节点用于它们包含的下一个和上游指针。要测试是否已到达列表的末尾,而不是测试空指针,请测试指针是否指向sentinel节点。
如果您希望列表元素较小,或者您的列表非常大,则可以使用普通节点作为您的标记。你在空间上浪费了一些内存,用于不使用的元素,但这可能不是什么大问题。如果你真的关心内存效率(比如,你正在编写一个库),你可以这样:
template<typename T> class dlist {
struct node_header {
node_header* next;
node_header* prev;
};
struct node : public node_header {
T element;
};
// Convert a node_header pointer to a node pointer
node* node_from_header(node_header* p) {
return static_cast<node*>(p);
}
};
使用这种方法,您的前哨节点是node_header
,所有包含元素的实际节点都是node
。您的内部算法都可以在node_header
上运行,直到您需要实际检索节点的元素,此时您使用node_from_header()
来检索包含元素的完整节点。
如果您绝对不想使用sentinel节点,则必须重写代码以直接使用头指针,而不是通过函数检索它,并添加用于处理空头指针的特殊情况代码。这不是一个很好的选择。