填充双向遍历的双链表

Filling a doubly linked list for bi-directional traversal

本文关键字:链表 填充 遍历      更新时间:2023-10-16

大家晚上好,我还有一个问题。和往常一样,如果这是重复的,请指向我正在复制的线程(如果我能找到它,我就不会发帖了)。我在github上浏览并更新了一些古老的代码,并将其重写为不那么愚蠢,最后遇到了理论和实现的问题。在双链接列表中(需要跟踪头和尾),应该如何初始化第一个成员?从前面推动会留下未初始化(或未正确初始化)的尾部,反之亦然。

我的意思是

template <typename T>
void double_list<T>::push_back(T data)
{
    if(tail)
    {
        node<T>* temp = new node<T>;
        temp->data = data;
        this->tail->next = temp;
        temp->prev = this->tail;
        this->tail = temp;
    }
    else
    {
        if(!head) //New list
        {
            this->head = new node<T>;
            this->tail = new node<T>;
            this->tail->data = data;
            this->tail->prev = this->head;
            this->head->next = this->tail;
        }
    }
}
template <typename T>
void double_list<T>::pop_back(T* out)
{
    if(this->tail->prev)
    {
            *out = this->tail->data;
            this->tail = this->tail->prev;
            this->tail->next = NULL;
            //numel -= 1;
    }
    else
        throw pop_empty();
}

main.cpp:

#include <iostream>
#include "list.h"
#include "list_inst.h"

using namespace std;
int main()
{
    double_list<int> myList1;
    double_list<int> myList2;
    double_list<int> myList3;
    double_list<int> myList4;
    bool finished = false;
    for(int i = 1; i <= 25; i++)
    {
        myList1.push_front(i);
        myList2.push_front(i);
        myList3.push_back(i);
        myList4.push_back(i);
    }
    cout << "First list (25 - 1) forward traversal:n";
    while(!finished)
    {
        try
        {
            int val = 0;
            myList1.pop_front(&val);
            cout << val << ", ";
        }
        catch(pop_empty &bad_pop)
        {
            finished = true;
        }
    }
    cout << "nn";
    finished = false;
    cout << "Second list (25 - 1) reverse traversal:n";
    while(!finished)
    {
        try
        {
            int val = 0;
            myList2.pop_back(&val);
            cout << val << ", ";
        }
        catch(pop_empty &bad_pop)
        {
            finished = true;
        }
    }
    cout << "nn";
    finished = false;
    cout << "Third list (1 - 25) forward traversal:n";
    while(!finished)
    {
        try
        {
            int val = 0;
            myList3.pop_front(&val);
            cout << val << ", ";
        }
        catch(pop_empty &bad_pop)
        {
            finished = true;
        }
    }
    cout << "nn";
    finished = false;
    cout << "Fourth list(1 - 25) reverse traversal:n";
    while(!finished)
    {
        try
        {
            int val = 0;
            myList4.pop_back(&val);
            cout << val << ", ";
        }
        catch(pop_empty &bad_pop)
        {
            finished = true;
        }
    }
    cout << "nn";
    finished = false;
    return 0;
}

当遍历样式匹配时(前与前,后与后),没问题,但我想让它更灵活一点,坦率地说,学习一些我在学校时教授们从未提及的东西。任何批评都是受欢迎的,因为我在这里发帖只是为了学习。提前感谢!

头和尾不需要额外的节点。如果列表由一个元素组成,则头和尾指向同一个元素。

template <typename T>
void double_list<T>::push_back(T data)
{
    if ( tail != nullptr )
    {
        node<T>* temp = new node<T>;
        temp->data = data;
        this->tail->next = temp;
        temp->prev = this->tail;
        this->tail = temp;
    }
    else
    {
        this->tail = this->head = new node<T>;
        this->tail->prev = this->head->next = nullptr;
        this->tail->data = data;
    }
}
template <typename T>
void double_list<T>::pop_back(T* out)
{
    if ( this->tail != nullptr )
    {
        node<T>* temp = this->tail;
        *out = this->tail->data;
        if ( this->tail->prev != nullptr )
        {
            this->tail = this->tail->prev;
            this->tail->next = NULL;
        }
        else
            this->tail = this->head = nullptr;
        delete temp;
    }
    else
        throw pop_empty();
}

参考n.m的注释,c++的解是std::list