双引导列表头被取消引用为空

时间:2017-03-06 18:34:21

标签: c++ doubly-linked-list

我的头指针应该是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;
};

2 个答案:

答案 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节点,则必须重写代码以直接使用头指针,而不是通过函数检索它,并添加用于处理空头指针的特殊情况代码。这不是一个很好的选择。