双端队列:这是一个合理的"add to front"实现吗?

Double-Ended Queue: is this a sound "add to front" implementation?

本文关键字:add to front 实现 一个 队列      更新时间:2023-10-16

我正在研究双端队列作为双链表的实现(为了个人充实),我想知道是否有人介意看看我的PushFront函数,看看我是否在正确的轨道上。它本身应该是不言自明的(我希望)。

void DeQueue::PushFront(void* item) {
    QueueItem* temp = new QueueItem();
    temp->data = item;
    // Insert the item between the head and the head's next item.
    if (Empty()) {
        head->next = temp;
        tail->last = temp;
        temp->next = tail;
        temp->last = head;
    } else {
        temp->next = head->next;
        temp->last = head;
        head->next->last = temp;
        head->next = temp;
    }
}

我的想法是,我的头和尾哨兵保持在两端,这对我来说似乎是避免边缘情况的最好方法。

EDIT:为了避免任何混淆,我知道这已经在标准库中为我完成了。我这样做是为了自学一些关于这门语言的东西。

编辑:看来我明白了。现在有一个有趣的问题:

void* DeQueue::PopFront() {
    if (Empty()) return NULL;  // should throw exception instead.
    void* temp = head->next->data;
    head->next->next->last = head;
    head->next = head->next->next;
    // now my node is gone... How do i free the memory
    // of something I've lost the reference to?
    return temp;
}

关于哨兵,您只需要其中一个包含列表的next(第一个)和last指针。如果在初始化时让指针指向哨兵值,那么就不需要考虑列表为空时的特殊情况。

关于第二个问题,弹出列表,你只需要保持一个指向节点的指针,并在从函数返回之前调用delete

另外,你可能想考虑划分学习的问题:使用智能指针来管理你的资源和学习算法,然后学习内存管理(反之亦然)

对第二次编辑的回答:你不能。您必须保留对它的引用。

void* DeQueue::PopFront() {
    if (Empty()) 
        throw logic_error("stack is empty");
    QueueItem* deleteme = head->next; //get node
    void* temp = deleteme->data;
    deleteme->next->last = head;
    head->next = deleteme->next;
    delete deleteme; //delete node
    return temp;
}

with this

if (Empty()) {
    head->next = temp;
    tail->last = temp;
    temp->next = tail;
    temp->last = head;

当队列为空时,你假定头和尾已经指向某个东西?