【问题标题】:Use a vector to initialize the linked list in C++ [duplicate]在C ++中使用向量初始化链表[重复]
【发布时间】:2019-09-11 15:24:09
【问题描述】:

这是我的linked list 结构代码。我想使用一个向量来初始化 TreeNode。但是在构造函数中,ptr->next = tem 有错误Exception thrown: write access violation. ptr was 0xCDCDCDCD. 有人知道原因以及如何更正吗?

#include<iostream>
#include<vector>

using namespace std;

struct ListNode {
    int val = 0;
    ListNode* next = NULL;

    ListNode(int val) : val(val){};

    ListNode(vector<int> vec) {
        if (vec.empty())
            return;
        val = vec[0];
        ListNode* ptr = this;
        for (int i = 1; i < vec.size();i++)
        {
            ptr->next = new ListNode(vec[i]);
            ptr = ptr->next;
        }
    }
};

【问题讨论】:

  • 您有什么理由不使用std::list 而不是您自己的?
  • @user6703592 这种方法没有意义。节点不能由向量初始化。它是一个可以由向量初始化的列表。
  • 看来您从根本上误解了new 和delete。如果您 delete tem; 则 tem 以及指向同一对象的所有其他指针都将失效。 delete 不会“释放”指向对象的指针(指针不是任何类型的引用计数句柄)它会删除指针指向的实际对象。
  • 如果你有向量,为什么还要使用链表呢?
  • 该代码在我看来是随机的。你能向橡皮鸭解释它的每一行应该做什么以及为什么会在那里吗?

标签: c++ vector constructor linked-list singly-linked-list


【解决方案1】:

对于初学者来说,这是一个糟糕的设计。用向量的元素初始化节点是没有意义的。

它是一个列表,可以由向量的元素而不是节点来初始化。

构造函数ListNode的定义也没有意义。

例如它的数据成员next没有被初始化。

    ListNode* ptr = next;

所以这个说法

        ptr->next = tem;

调用未定义的行为。

一个节点被分配然后被删除

        ListNode* tem = new ListNode(*it);
        // ...
        delete tem;

那么列表将包含什么?:)

另外,使用这样的 typedef 也是一个坏主意

typedef vector<int>::iterator vit;

它只会让代码的读者感到困惑。

该类可以通过以下方式定义,如演示程序中所示。当然,您自己需要在类定义中附加其他构造函数、赋值运算符和析构函数。

#include <iostream>
#include <vector>

class List 
{
protected:
    struct Node
    {
        int val;
        Node *next;
    } *head = nullptr;      

public:

    explicit List() = default;

    List( const std::vector<int> &v )
    {
        Node **current = &head;

        for ( const auto &value : v )
        {
            *current = new Node { value, *current };
            current = &( *current )->next;
        }
    }

    friend std::ostream & operator <<( std::ostream &, const List & );
};

std::ostream & operator <<( std::ostream &os, const List &list )
{
    for ( List::Node *current = list.head; current != nullptr; current = current->next )
    {
        os << current->val << " -> ";
    }

    return os << "nullptr";
}

int main()
{
    std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    List list( v );

    std::cout << list << '\n';
}

程序输出是

0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> nullptr

由于接受向量的列表的构造函数不是显式的,因此您可以通过以下方式声明列表

List list( { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } );

【讨论】:

    【解决方案2】:

    在第一次迭代中,“next”将未初始化,因此 ptr->next 不会指向任何有意义的内容,并且可能会导致段错误。

    这不是方法中唯一的错误。

    此外,在调试模式下,一些编译器会在未初始化的内存中放置一个特定的位模式以帮助调试。 0xCDCDCDCD 看起来很像其中一种位模式。

    【讨论】:

    【解决方案3】:

    您的第一次迭代未正​​确初始化。

    试试

    ...
        ListNode(vector<int> vec) {
                 ListNode* ptr = this;
    ...
    

    它也没有正确对齐列表中的值。设置this 的值,然后继续使用迭代器

            vit it = vec.begin();
            val = *it;
    
            for ( ++it; it != vec.end(); it++)
            {
                ListNode* tem = new ListNode(*it);
                ptr->next = tem;
                ptr = ptr->next;
            }
    

    改为

    【讨论】:

      猜你喜欢
      • 2012-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-17
      • 1970-01-01
      • 1970-01-01
      • 2018-03-01
      • 2015-09-20
      相关资源
      最近更新 更多