-9

So, I've been stuck these past three days trying to delete the minimum pointer of the doubly linked list. It always crashes at the point I use min = a.erase(min). I did research saying you "should" delete first using "delete(*min)" but it wont compile. Right now I am focused on deleting one value then I will add the for loop to go through n times for each small number again (i.e - I have to find minimum, print, delete, repeat until the end)

I had a code that was working but it wouldn't work all the time making me start over.

#include <cstdlib>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <iomanip>
typedef int Object;

using namespace std;
#include <cstdlib>
typedef int Object;

class List{
private:
// The basic doubly linked list node.
// Nested inside of List, can be public
// because the Node is itself private
    struct Node
    {
        Object  data;
        Node   *prev;
        Node   *next;

        Node(const Object & d = Object(), Node * p = NULL, Node * n = NULL)
            : data(d), prev(p), next(n) { }
    };

public:
    class const_iterator
    {
    public:

    // Public constructor for const_iterator.
        const_iterator() : current(NULL)
        { }

    // Return the object stored at the current position.
    // For const_iterator, this is an accessor with a
    // const reference return type.
        const Object & operator* () const
        {
            return retrieve();
        }

        const_iterator & operator++ ()
        {
            current = current->next;
            return *this;
        }

    const_iterator operator++ (int)
    {
        const_iterator old = *this;
        ++(*this);
        return old;
    }

    const_iterator & operator-- ()
    {
        current = current->prev;
        return *this;
    }

    const_iterator operator-- (int)
    {
        const_iterator old = *this;
        --(*this);
        return old;
    }

    bool operator== (const const_iterator & rhs) const
    {
        return current == rhs.current;
    }

    bool operator!= (const const_iterator & rhs) const
    {
        return !(*this == rhs);
    }

    protected:
    Node *current;

    // Protected helper in const_iterator that returns the object
    // stored at the current position. Can be called by all
    // three versions of operator* without any type conversions.
    Object & retrieve() const
    {
        return current->data;
    }

    // Protected constructor for const_iterator.
    // Expects a pointer that represents the current position.
    const_iterator(Node *p) : current(p)
    { }

    friend class List;
    };

    class iterator : public const_iterator
    {
    public:

    // Public constructor for iterator.
    // Calls the base-class constructor.
    // Must be provided because the private constructor
    // is written; otherwise zero-parameter constructor
    // would be disabled.
    iterator()
    { }

    Object & operator* ()
    {
        return retrieve();
    }

    // Return the object stored at the current position.
    // For iterator, there is an accessor with a
    // const reference return type and a mutator with
    // a reference return type. The accessor is shown first.
    const Object & operator* () const
    {
        return const_iterator::operator*();
    }

    iterator & operator++ ()
    {
        current = current->next;
        return *this;
    }

    iterator operator++ (int)
    {
        iterator old = *this;
        ++(*this);
        return old;
    }

    iterator & operator-- ()
    {
        current = current->prev;
        return *this;
    }

    iterator operator-- (int)
    {
        iterator old = *this;
        --(*this);
        return old;
    }

    protected:
    // Protected constructor for iterator.
    // Expects the current position.
    iterator(Node *p) : const_iterator(p)
    { }

    friend class List;
    };

public:
    List()
    {
        init();
    }

    ~List()
    {
    clear();
    delete head;
    delete tail;
    }

    List(const List & rhs)
    {
    init();
    *this = rhs;
}

const List & operator= (const List & rhs)
{
    if (this == &rhs)
        return *this;
    clear();
    for (const_iterator itr = rhs.begin(); itr != rhs.end(); ++itr)
        push_back(*itr);
    return *this;
}

// Return iterator representing beginning of list.
// Mutator version is first, then accessor version.
iterator begin()
{
    return iterator(head->next);
}

const_iterator begin() const
{
    return const_iterator(head->next);
}

// Return iterator representing endmarker of list.
// Mutator version is first, then accessor version.
iterator end()
{
    return iterator(tail);
}

const_iterator end() const
{
    return const_iterator(tail);
}

// Return number of elements currently in the list.
int size() const
{
    return theSize;
}

// Return true if the list is empty, false otherwise.
bool empty() const
{
    return size() == 0;
}

void clear()
{
    while (!empty())
        pop_front();
}

// front, back, push_front, push_back, pop_front, and pop_back
// are the basic double-ended queue operations.
Object & front()
{
    return *begin();
}

const Object & front() const
{
    return *begin();
}

Object & back()
{
    return *--end();
}

const Object & back() const
{
    return *--end();
}

void push_front(const Object & x)
{
    insert(begin(), x);
}

void push_back(const Object & x)
{
    insert(end(), x);
}

void pop_front()
{
    erase(begin());
}

void pop_back()
{
    erase(--end());
}

// Insert x before itr.
iterator insert(iterator itr, const Object & x)
{
    Node *p = itr.current;
    theSize++;
    return iterator(p->prev = p->prev->next = new Node(x, p->prev, p));
}

// Erase item at itr.
iterator erase(iterator itr)
{
    Node *p = itr.current;
    iterator retVal(p->next);
    p->prev->next = p->next;
    p->next->prev = p->prev;
    delete p;
    theSize--;

    return retVal;
}

iterator erase(iterator start, iterator end)
{
    for (iterator itr = start; itr != end; )
        itr = erase(itr);

    return end;
}

private:
int   theSize;
Node *head;
Node *tail;

void init()
{
    theSize = 0;
    head = new Node;
    tail = new Node;
    head->next = tail;
    tail->prev = head;
}
};

int main()
{
    size_t n;
    cout << "Please enter the amount of random numbers to be generated " <<           endl;
    cin >> n;
    int randomRange;
    List a;

    srand(time(NULL));


    for (int i = 0; i < n;i++) {
        randomRange = rand() % 10000 + 1;
        a.insert(a.end(), randomRange);
    }

    cout << endl;
    //a.erase(--a.end());
    cout << "The size is: " <<a.size() << endl;
    cout << endl;
    for (List::iterator it = a.begin();it != a.end(); ++it)
    {
        cout << *it << endl;
    }
    //List::iterator it = a.begin();
    List::iterator min = a.begin();

    cout <<  endl;
    //cout << *min << endl;
    for (List::iterator it = a.begin();it != a.end(); ++it) {
        //++min;

            if (*it < *min) {
                //cout <<"1st it is : "<< *it << endl;
                //cout << "1st min is : " << *min << endl;
                *min = *it;
                //cout <<"this is min"<< *it << endl;




                //cout << "check" << endl;
                //cout << "smallest" << *min << endl;
            }


            //cout << "after if loop it is : " << *it << endl;
        //  cout << "after if loop min is : " << *min << endl;
            //cout << "check2" << endl;
    }
    cout <<"small" << *min << endl;
    //delete (*it);

    while (min != a.end())
    {
         a.erase(min);
    }

    for (List::iterator min ;min != a.end(); ++min)
    {
        cout << *min << endl;
    }
    return 0;
  • 7
    [TL;DR!](https://en.wikipedia.org/wiki/TL;DR) Please try to create a [*Minimal*, Complete, and Verifiable Example](http://stackoverflow.com/help/mcve) and show us. – Some programmer dude Feb 16 '16 at 07:41
  • When you call `a.erase(min)` the iterator is invalidated. Use `min = a.erase(min)`. – Jonas Feb 16 '16 at 07:43
  • I used that as well earlier. same issue. crash. – user1072583 Feb 16 '16 at 07:52
  • You could consider to replace `typedef int Object;` with a template parameter. – Jonas Feb 16 '16 at 08:13
  • @user1072583 You should mark your questions (all of them) as answered, if there is a useful answer. This is done by clicking the check mark (v-like symbol) of one of the answers. – Jonas Feb 16 '16 at 09:37

1 Answers1

0

When you call a.erase(min) the iterator min is invalidated. Use min = a.erase(min), since the erase function returns the next iterator.

EDIT: However, that change does not do what you want. Here is what the Main function should be:

int main()
{
    size_t n;
    cout << "Please enter the amount of random numbers to be generated " <<           endl;
    cin >> n;
    int randomRange;
    List a;

    srand(time(NULL));


    for (int i = 0; i < n;i++) {
        randomRange = rand() % 10000 + 1;
        a.insert(a.end(), randomRange);
    }

    cout << endl;
    cout << "The size is: " <<a.size() << endl;
    cout << endl;
    for (List::iterator it = a.begin();it != a.end(); ++it)
    {
        cout << *it << endl;
    }

    cout <<  endl;

    while (a.size()) // Repeat until size is zero
    {
        List::iterator min = a.begin(); // Initialize the minimum iterator
        for (List::iterator it = a.begin();it != a.end(); ++it) {

                if (*it < *min)
                {
                    // New minimum found, save iterator, not value.
                    min = it;
                }
        }
        cout <<"small: " << *min << endl; // print the minimum
        a.erase(min);  // Erase the minimum
    }

    return 0;
}

EDIT: Alternatively you could sort your list and then just print the content. The main function could then be:

int main()
{
    size_t n;
    cout << "Please enter the amount of random numbers to be generated " <<           endl;
    cin >> n;
    int randomRange;
    List a;

    srand(time(NULL));


    for (size_t i = 0; i < n;i++) {
        randomRange = rand() % 10000 + 1;
        a.insert(a.end(), randomRange);
    }

    cout << endl;

    cout << "The size is: " <<a.size() << endl;
    cout << endl;
    for (List::iterator it = a.begin();it != a.end(); ++it)
    {
        cout << *it << endl;
    }
    cout <<  endl;

    // Use bubble sort
    for (List::iterator it1 = a.begin(); it1 != a.end(); ++it1)
    for (List::iterator it2 = a.begin(); it2 != it1; ++it2)
    {
        List::iterator it3 = ++it2; --it2; // Your iterators does not support arithmetic...
        if (*it2 > *it3)
        {
            std::swap(*it2, *it3);
        }
    }

    for (List::iterator min = a.begin() ;min != a.end(); ++min)
    {
        cout << *min << endl;
    }
    return 0;
}
Jonas
  • 6,915
  • 8
  • 35
  • 53