简体   繁体   中英

Adding value to singly-linked list

I'm in a C++ data structures class and a recent homework assignment has been bugging me for days. It has to deal with working with singly-linked lists, and one of the methods we have to write has to do with adding values to the list.

First off, we create the dummy node head :

template<typename T>
SLList<T>::SLList()
{
  head = new Node; // Node() is ok too
}

If I'm correct, this shouldn't hold a value, should it? So head should be NULL . This is what I've managed to create (with my professor's help) so far.

template<typename T>
void SLList<T>::add(const T& val) {
    bool duplicate = false;
    //Node *ptr = head->next;
    //cout << head->data;

    for (Node *ptr = head->next; ptr != NULL; ptr = ptr->next) {
    //while (ptr == NULL) {
        //ptr = ptr->next;
        // if ptr is initialized as head, the first node, then ptr != NULL
        // if ptr is initialized as head->next, which it should in order to
        // traverse from the node AFTER the head, then ptr == NULL
        // not exactly sure why.
        if (ptr->data == val) {
            duplicate = true;
            break;
        }
    }
    //Node *temp = new Node(val); // create new node with new element.
    //temp->next = ptr->next;
    //ptr->next = temp;

    if (duplicate) {
        cout << "Duplicate entry found: " << val << endl;
    }
}

I've tried working with for and while loops, since a lot of google results used while loops in their answers. What I'm trying to do is attempt to add a value to the list. If the value is already in that list, it doesn't get added. I'm attempting this with:

SLList<int> iList;
iList.add(5);
iList.add(6);
iList.add(6);

When I asked for help, I was told that I should initialize *ptr as head->next to start traversing the list for the node AFTER the dummy node. I used Visual Studio's debugger and found that after initializing it to head->next the program never went into the for loop, which I'm assuming is because the node after the dummy node fails the if statement ptr != NULL . I'm not exactly sure why that is, as when I had Node *ptr = head it would traverse through the list just fine (although the following line if (ptr->data == val) would consider every entry a duplicate entry).

I'm probably understanding this wrong, but shouldn't the head node have a value of NULL ? So it shouldn't pass the if statement in the for loop.

There also seems to be a problem with the three lines after the for loop, since when the program gets down there, it just crashes and fails to add any values to the list, but I figured I'd just take it one step at a time.

There's probably a lot here I'm misunderstanding, so any help at all would be appreciated.

Try something like this:

template<typename T>
void SLList<T>::add(const T& val) {
    Node<T>* prev = head;
    for (Node<T>* ptr = head->next; ptr; ptr = ptr->next) {
        if (ptr->data == val) {
            std::cout << "Duplicate: " << val << '\n';
            return;
        }
        prev = ptr;
    }
    prev->next = new Node<T>(val);
}

Your main design flaw here seems to be this: You're going to the end of your list and taking it from there but the end is null so you need to backtrack once to find something that is not null. For instance (basic example)

Node<T>* last = head;
for(Node<T>* ptr = head->next; ptr != NULL ; ptr = ptr->next){
    last = ptr;
    //do something
}

So when the loop is over, you know that if ptr==NULL then last is the tail of your list and anything you want to add must follow it.

This is also the problem in the three lines of code after the for loop: If I am understanding you correctly, in the case that there is no duplicate, you are iterating until ptr is NULL . So when exiting the for, ptr->next will fail. This means that when adding an element, if that element is not in the list - your function fails (by design and not by accident).

HEAD

When the list is empty, head must be NULL. This happens at creation or after adding and deleting equal number of nodes. In all other situations, head must be non-NULL, and it must point to the first added node.

ADD (typical)

Node * ptr = new Node;
ptr->next = head;
head = ptr;

ADD (only non-duplicate)

bool const exists = std::find( list, element );
if( ! exists ) {
    Node * ptr = new Node;
    ptr->next = head;
    head = ptr;
}

You have a couple of options here. The most common is that you set your head pointer to nullptr until you add a node. In this case, you simply never had (or need) a dummy node at all.

Another possibility is to create the list initially containing a dummy node. This can simplify the rest of the code somewhat, as it avoids having any special case code for adding the first node to an empty list. You can also use the dummy node as a "sentinel", containing some data item that's not allowed throughout the rest of the list. Under the right circumstances, this can simplify list traversal by allowing you to only look at the contained data instead of ever checking for a null pointer signaling the end of the list. A prime example is a list of floating point numbers that you keep in sorted order, with the dummy node containing an infinity . In this case, finding a number can be simplified from:

while (ptr != nullptr && ptr->data < search_item) {
    // ...
    ptr=ptr->next;
}

...to just:

while (ptr->data < search_item) {
    // ...
    ptr = ptr->next;
}

The infinity at the end of the list ensures that if nothing else in the list is greater than search_item , the dummy node will be (though this obviously requires that you ensure against inserting an item into the list with infinity as its value).

This, however, differs from the usage you suggest in the question--it requires that the dummy node always remain as the last item in the list, so you never insert anything after it. At least in my experience, however, this is more common than a dummy node that's always at the beginning of the list.

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