【问题标题】:Problem with [] operator in doubly linked list c++双向链表c ++中[]运算符的问题
【发布时间】:2021-06-04 20:50:52
【问题描述】:

我是一个真正的 c++ 初学者,我被添加了一个任务,即编写一个包含基本方法和运算符的类似 stl 的双向链表。所以我做了一些基本的方法,但是当我使用 [ ] 运算符编译代码后它会打印“分段错误”错误。我很乐意在解决这个问题方面得到一些帮助。

#include <iostream>
using namespace std;

template<typename T>
class Node
{
    public:
        T data;
        Node *prev;
        Node *next;
        Node(T data, Node *prev = nullptr, Node *next = nullptr): data(data), prev(prev), next(next) {}

};

template<typename T>
class List
{
    public:
        T& operator[](T const index);
        List();
        List(const List&);
        ~List();
        bool empty();
        int size();
        void clear();
        void push_back(T data);
        void push_front(T data);
        void pop_back();
        void pop_front();
        void resize(int nums);
    private:
        int Size;
        Node<T> *tail;
        Node<T> *head;
};

template<typename T>
List<T>::List()
{
    Size = 0;
    head = nullptr;
    tail = nullptr;
}

template<typename T>
List<T>::List(const List & L)
{
    head = nullptr;
    tail = nullptr;
    int count = 0; 
    Node<T> *temp = head;
    while(temp)
    {
        push_back(temp->data);
        temp = temp->next;
    }
}

template<typename T>
List<T>::~List()
{
    Node<T> *temp;
    while(head)
    {
        temp = head;
        head = head->next;
        delete temp;
    }
}

template<typename T>
T & List<T>::operator[](T const index)
{
    Node<T> *curr = head;
    int counter = 0;
    while (curr)
    {
        if (counter == index)
        {
            return curr->data;
        }
        curr = curr->next;
        counter++;
    }
}

template<typename T>
void List<T>::push_back(T data)
{
    if (head == nullptr)
    {
        head =  new Node<T>(data, tail, nullptr);
    }
    if (tail != nullptr)
    {
        tail->next = new Node<T>(data, tail, nullptr);
    }
    tail = new Node<T>(data, tail, nullptr);
    ++Size;

}

template<typename T>
void List<T>::push_front(T data)
{
    head = new Node<T>(data, nullptr, head);
    Size++;
}

template<typename T>
void List<T>::pop_back()
{
    Node<T> *temp = tail;
    tail = tail->prev;
    delete temp;
    Size--;
}

template<typename T>
void List<T>::pop_front()
{
    Node<T> *temp = head;
    head = head->next;
    delete temp;
    Size--;
}

template<typename T>
void List<T>::clear()
{
    while (Size)
    {
        pop_back();
    }
}

template<typename T>
void List<T>::resize(int num)
{
    if (num > Size)
    {
        while (Size != num)
        {
            push_back(0);
        }
    }
    else{
        while (Size != num)
        {
            pop_back();
        }
    }
}

template<typename T>
bool List<T>::empty() {return Size == 0;}

template<typename T>
int List<T>::size() {return Size;}

int main()
{
    List<int> l;
    l.push_back(1234);
    l.push_back(124);
    l.push_back(10);
    l.push_front(1);

    for (int i = 0; i < l.size(); i++)
    {
        cout<<l[i]<<" ";
    }

    return 0;
}

【问题讨论】:

  • 从学习使用调试器开始。
  • 不相关:由于链表不是随机访问数据结构(如果不访问它们之间的所有节点,就不能从 0 变为 10),使用运算符 [] 有什么意义?
  • 编译器在这里也可能有所帮助。它应该警告没有return 的路径。
  • @eerorika 这有点苛刻。那家伙说他是初学者,他显然已经为此付出了努力。你可以让他放松一些,变得更好。
  • 您可以给初学者的一些最佳建议是掌握调试器的使用。它可能是仅次于编译器的第二好的程序员生产力工具。在我上大学之前尽早搞清楚 turbo 调试器可能是我在大学期间还有时间运行 AD&D 游戏的唯一原因。

标签: c++ doubly-linked-list


【解决方案1】:
if (tail != nullptr)
{
    tail->next = new Node<T>(data, tail, nullptr);
}
tail = new Node<T>(data, tail, nullptr);

这是你最大的错误。在tail 之后添加next,但随后将tail 设置为不同的值。所以,下次你推送的时候,你会推送到新的tail,而不是从head开始的nexts的链。因此,您的列表比预期的要短,并且您将其遍历到末尾。

你可能想要这样的东西:(未测试)

if (tail != nullptr)
{
    tail->next = new Node<T>(data, tail, nullptr);
    tail = tail->next;
}
else
{
    tail = new Node<T>(data, tail, nullptr);
}

【讨论】:

  • 这可以进一步简化:Node *n = new Node&lt;T&gt;(data, tail, nullptr); if (!head) { head = n; } if (tail) { tail-&gt;next = n; } tail = n;
  • 请注意 Remy 的评论。如果头尾成员维护得当,if (tail)可以替换为else
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-28
相关资源
最近更新 更多