简体   繁体   中英

Pointers in linked list not working as expected

This realization of linked list is broken. Address of nodes[0].next doesn't match the nodes[1] address. So nodes[1].next is NULL (as default value). I added some address printing to the search method. It looks like the nodes[1] wasn't initialized?

#include <iostream>
#include <vector>

using namespace std;

typedef struct Node_T {
    int data;
    Node_T *next;
} Node;

class LinkedList{
    public:
        vector<Node> nodes;
            LinkedList(){
        }

        void insert(int data) {
            Node temp_node;
            temp_node.data = data;
            temp_node.next = NULL;

            size_t len = nodes.size();
            nodes.push_back(temp_node);
            if (len > 0) {
                nodes[len - 1].next = &nodes[len];
            }
        }

        int search(int val){
            if (nodes.empty())
                return -1;

            Node *node_ptr = &nodes[0];

            // Debug
            cout << &nodes[1] << "\n";
            cout << &nodes[0].next << "\n";

            int i = 0;
            do {
                if (node_ptr->data == val) return i;
                    i++;
            } while((node_ptr = node_ptr->next) != NULL);

            return -1;
        }

};

int main()
{
    LinkedList llist;
    llist.insert(1);
    llist.insert(2);
    llist.insert(3);
    llist.insert(4);
    llist.insert(5);
    cout << llist.search(3) << "\n";

    return 0;
}

It shows me: 0x8e6a060 0x8e6a05c -1

When you add elements to a vector , references to (and hence addresses of) vector elements are invalidated. You must therefore not use values such as &nodes[0] or &nodes[len] , as they are meaningless.

The point with an exercise like this is to get the hang of the internal structure in a linked list. You have replaced that internal structure with a vector<Node> .

Instead of a vector, the idea is to have a

private:
    Node* head;

As you data member.

In your insert function you are supposed to dynamically allocate memory for the Node with

Node* newNodePointer = new Node;

And manipulate the pointer with next and such.

It is worth to point out, that this is fine as an exercise, but your "real" code should use standard library facilities.

First, Your printout is incorrect: this line

cout << &nodes[0].next << "\n";

prints the address of next , rather than printing the next itself. Changing to

cout << nodes[0].next << "\n";

gives the correct printout ( demo ).

However, the main issue is that you keep pointers to elements of std::vector . These become invalid after the first write, because new storage gets allocated for the growing vector.

You can certainly work around this by reserving sufficient space upfront (call nodes.reserve(1000) from the constructor of your list; demo ) but that is merely a hack: you should use new and delete to allocate elements of your linked list manually. That is the whole point of this exercise.

But I still need a container to ensure that nodes will be live as expected?

No, you do not. Your class is a container. By referencing the whole chain of nodes from the head pointer it can ensure that the entire chain is kept "live".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM