0

I implemented a Stack class and tried to make use of that class to solve Hanoi Problem. Here is my code:

template<class Datatype>
class Node
{
    public:
        Node()
        {
            next = NULL;
            prev = NULL;
        }
        Node* getNext()
        {
            return next;
        }
        Node* getPrev()
        {
            return prev;
        }
        Datatype* getData()
        {
            return &data;
        }
        void changeNext()
        {
            next = NULL;
        }
        void changeNext(Node& nextNode)
        {
            next = &nextNode;
        }
        void changePrev()
        {
            prev = NULL;
        }
        void changePrev(Node& prevNode)
        {
            prev = &prevNode;
        }
        Node* addNext(Node &);
        Node* addPrev(Node &);
        void nodeDel();
        void addData(Datatype &);
    private:
        Node* next;
        Node* prev;
        Datatype data;
};

template<class Datatype>
class Stack
{
    public:
        Stack() : head( NULL )
        {

        }
        virtual ~Stack()
        {
            Datatype temp;
            while (pop(temp));
            cout << "Stack released all spaces" << endl;
        }
    public:
        virtual int push(Datatype &);
        virtual int pop(Datatype &);
        virtual Datatype* peek();
    protected:
        Node<Datatype> *head;
};
template <class Datatype>
int Stack<Datatype>::push(Datatype &new_data)
{
    Node<Datatype> *pt_node = new Node<Datatype>;
    if (pt_node == NULL)
        return -1;

    pt_node -> addData(new_data);

    if (head == NULL)
        head = pt_node;
    else
    {
        pt_node -> addPrev(*head);
        head = pt_node;
    }

    //cout << *(head -> getData()) << endl;

    return 0;
}

template <class Datatype>
int Stack<Datatype>::pop(Datatype &pop_data)
{
    if (head == NULL)
        return 0;

    pop_data = *(head -> getData());

    if (head -> getNext() == NULL)
    {
        delete head;
        head = NULL;
    }
    else
    {
        Node<Datatype>* temp = head;
        head = head -> getNext();
        delete temp;
    }

    return 1;
}

Above declare Stack class and also implement pop() and push() functions. Now, I declare my Hanoi class and implement functions.

class Hanoi
{
    public:
        Hanoi(int num) : a_tower(), b_tower(), c_tower()
        {
            deep = num;
            int i;
            for (i = num; i != 0; i --)
                a_tower.push(i);
        }
    public:
        void workdone(int, Stack<int>&, Stack<int>&, Stack<int>&);
        void showret();
    public:
        Stack<int> a_tower;
        Stack<int> b_tower;
        Stack<int> c_tower;
        int deep;
};  

void Hanoi::workdone(int deep_num, Stack<int>& A, Stack<int>& B, Stack<int>& C)
{
    int temp;
    if (deep_num == 1)
    {
        A.pop(temp);
        C.push(temp);
    }       
    else
    {
        Hanoi::workdone(deep_num - 1, A, C, B);
        A.pop(temp);
        C.push(temp);
        Hanoi::workdone(deep_num - 1, B, A, C);
    }
}

void Hanoi::showret()
{
    int temp;
    while (c_tower.pop(temp) != 0)
        cout << temp << endl;
}

Here is my test code:

int main()
{
    Hanoi test(STACK_DEEP);
    test.workdone(STACK_DEEP, test.a_tower, test.b_tower, test.c_tower);
    test.showret();

    return 0;
}

The output is:

*** glibc detected *** ./3_4: double free or corruption (fasttop): 0x090c0038 ***

I think this problem happens when ~Hanoi is called, but I really don't know why this would happen.

Here, I post the entire code which could get this result: my_node.h

#include <iostream>

using namespace std;

template<class Datatype>
class Node
{
    public:
        Node()
        {
            next = NULL;
            prev = NULL;
        }
        Node* getNext()
        {
            return next;
        }
        Node* getPrev()
        {
            return prev;
        }
        Datatype* getData()
        {
            return &data;
        }
        void changeNext()
        {
            next = NULL;
        }
        void changeNext(Node& nextNode)
        {
            next = &nextNode;
        }
        void changePrev()
        {
            prev = NULL;
        }
        void changePrev(Node& prevNode)
        {
            prev = &prevNode;
        }
        Node* addNext(Node &);
        Node* addPrev(Node &);
        void nodeDel();
        void addData(Datatype &);
    private:
        Node* next;
        Node* prev;
        Datatype data;
};

template<class Datatype>
class Stack
{
    public:
        Stack() : head( NULL )
        {

        }
        virtual ~Stack()
        {
            Datatype temp;
            while (pop(temp));
            cout << "Stack released all spaces" << endl;
        }
    public:
        virtual int push(Datatype &);
        virtual int pop(Datatype &);
        virtual Datatype* peek();
    protected:
        Node<Datatype> *head;
};

template <class Datatype>
Node<Datatype>* Node<Datatype>::addNext(Node<Datatype>& exi_node)
{
    if (exi_node.getNext() == NULL)
    {
        changePrev(exi_node);
        exi_node.changeNext(*this);
    }
    else
    {
        Node* next = exi_node.getNext();
        changePrev(exi_node);
        changeNext(*next);
        exi_node.changeNext(*this);
        next -> changePrev(*this);
    }
    return &exi_node;
}

template <class Datatype>
Node<Datatype>* Node<Datatype>::addPrev(Node<Datatype>& exi_node)
{
    if (exi_node.getPrev() == NULL)
    {
        changeNext(exi_node);
        exi_node.changePrev(*this);
    }
    else
    {
        Node* prev = exi_node.getPrev();
        changePrev(*prev);
        changeNext(exi_node);
        exi_node.changePrev(*this);
        prev -> changeNext(*this);
    }
    return &exi_node;
}

template<class Datatype>
void Node<Datatype>::nodeDel()
{
    if (prev == NULL && next == NULL)
        ;
    else if (prev == NULL)
    {
        Node* next = getNext();
        next -> changePrev();
    }
    else if (next == NULL)
    {
        Node* prev = getPrev();
        prev -> changeNext();
    }
    else
    {
        Node* next = getNext();
        Node* prev = getPrev();
        next -> changePrev(*prev);
        prev -> changeNext(*next);  
    }
    delete this;
    return;
}

template <class Datatype>
void Node<Datatype>::addData(Datatype &new_data)
{
    data = new_data;
}

template <class Datatype>
int Stack<Datatype>::push(Datatype &new_data)
{
    Node<Datatype> *pt_node = new Node<Datatype>;
    if (pt_node == NULL)
        return -1;

    pt_node -> addData(new_data);

    if (head == NULL)
        head = pt_node;
    else
    {
        pt_node -> addPrev(*head);
        head = pt_node;
    }

    //cout << *(head -> getData()) << endl;

    return 0;
}

template <class Datatype>
int Stack<Datatype>::pop(Datatype &pop_data)
{
    if (head == NULL)
        return 0;

    pop_data = *(head -> getData());

    if (head -> getNext() == NULL)
    {
        delete head;
        head = NULL;
    }
    else
    {
        Node<Datatype>* temp = head;
        head = head -> getNext();
        delete temp;
    }

    return 1;
}

template <class Datatype>
Datatype* Stack<Datatype>::peek()
{
    if (head == NULL)
        return NULL;
    return (this->head)->getData();
}

3_4.h

#include <iostream>
#include "my_node.h"

using namespace std;

class Hanoi
{
    public:
        Hanoi(int num) : a_tower(), b_tower(), c_tower()
        {
            deep = num;
            int i;
            for (i = num; i != 0; i --)
                a_tower.push(i);
        }
    public:
        void workdone(int, Stack<int>&, Stack<int>&, Stack<int>&);
        void showret();
    public:
        Stack<int> a_tower;
        Stack<int> b_tower;
        Stack<int> c_tower;
        int deep;
};  

void Hanoi::workdone(int deep_num, Stack<int>& A, Stack<int>& B, Stack<int>& C)
{
    int temp;
    if (deep_num == 1)
    {
        A.pop(temp);
        C.push(temp);
    }       
    else
    {
        Hanoi::workdone(deep_num - 1, A, C, B);
        A.pop(temp);
        C.push(temp);
        Hanoi::workdone(deep_num - 1, B, A, C);
    }
}

void Hanoi::showret()
{
    int temp;
    while (c_tower.pop(temp) != 0)
        cout << temp << endl;
}

3_4.cpp

#include <iostream>
#include "3_4.h"

using namespace std;

#define STACK_DEEP 4

int main()
{
    Hanoi test(STACK_DEEP);
    test.workdone(STACK_DEEP, test.a_tower, test.b_tower, test.c_tower);
    test.showret();

    return 0;
}

The command I use:

g++ -Wall 3_4.cpp -o 3_4
Shanpei Zhou
  • 371
  • 1
  • 2
  • 17
  • 3
    The `Node` class is still missing. Please insert the definition in your question or provide a link to a working example replicating the error. – Tim Mar 04 '14 at 21:34
  • 1
    Does nobody these days know how to use a debugger anymore? – hildensia Mar 04 '14 at 21:55
  • 1
    yes as Vlad already mentioned there is no need to have a double linked list for a stack since you are only inserting/deleting at one end. Just use a single linked list instead where `head` points to the top of the stack. If you insist on having a double linked list then at least update both pointers when you do push/pop – AndersK Mar 04 '14 at 22:04
  • @Claptrap The problem is that it is difficult to read his code. He made from a simple data structure a very compound code that only confuses readers. It is an example how code shall not be written.:) – Vlad from Moscow Mar 04 '14 at 22:23
  • @VladfromMoscow yes i agree, using weird names for simple things like setting a null ptr (changePrev) do not add value. – AndersK Mar 05 '14 at 07:21

1 Answers1

3

The code is more complicated (and confusing) than it needs to be, but the error boils down to an incorrect implementation of Node::addPrev

The minimal fix is to change the implementation of this function to:

    template <class Datatype>
    Node<Datatype>* Node<Datatype>::addPrev(Node<Datatype>& exi_node)
    {
        exi_node.prev = this;
        this->next = &exi_node;
        return &exi_node;
    }

A proper fix will involve changing the Stack and Node class to a simpler implementation -- as previous commenters have mentioned, it does not need to be a double-linked list.

ganz
  • 164
  • 4