C ++堆栈实现(作业)PT。 II

时间:2011-10-11 01:53:43

标签: c++ data-structures stack linked-list

好在这里取得进展。我的问题现在涉及复制构造和深层复制。我的堆栈目前一直在崩溃,我觉得它正在这样做,因为它所依赖的类不允许复制构造和运算符重载。但无论如何这里是我的代码(我为代码量道歉,但可能有必要了解我失败的地方):

依赖类,链表

#ifndef linkList_H
#define linkList_H


//
// Create an object to represent a Node in the linked list object
// (For now, the objects to be put in the list will be integers)
//
struct Node
{
    int   number;
    Node* next;
    Node* prev;

    // needs copy constructor?
    // needs overloaded assignment operators for copying?
    // needs overloaded operators for incrementing and decrementing?
};


//
// Create an object to keep track of all parts in the list
//
class List
{
public:

    //
    // Contstructor intializes all member data
    //
    List() : m_size(0), m_listHead(0) {}

    //
    // methods to return size of list and list head
    //
    Node*    getListHead() const { return m_listHead; }
    unsigned getListSize() const { return m_size; }

    //
    // methods for adding and inserting a new node to the linked list, 
    // retrieving and deleting a specified node in the list
    //
    void  addNode(int num);
    void  deleteNode(Node* current);
    void  insertHead(Node* current);
    void  insertAfter(Node* current, int newValue);
    void  insertBefore(Node* current, int newValue);

    Node* retrieveNode(unsigned position);

private:

    //
    // member data consists of an unsigned integer representing
    // the list size and a pointer to a Node object representing head
    //
    Node*    m_listHead;
    unsigned m_size;
};

#endif

实施linkedList

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

using namespace std;


//
// Adds a new node to the linked list
//
void List::addNode(int num)
{
    Node *newNode = new Node;
    newNode->number = num;
    newNode->next = m_listHead;

    if( m_listHead )
        m_listHead->prev = newNode;

    m_listHead = newNode;
    ++m_size;
}


//
// Inserts a node which has already been set to front
// of the list
//
void List::insertHead(Node* current)
{
    int value = current->number;
    deleteNode(current);
    addNode(value);
}


//
// Inserts a node which has already been set before a
// specified location in the list
//
void List::insertBefore(Node* current, int newValue)
{
    current = current->prev;
    current->number = newValue;
}


//
// Inserts a node which has already been set before a
// specified location in the list
//
void List::insertAfter(Node* current, int newValue)
{
    current = current->next;
    current->number = newValue;
}


//
// Deletes a node from a specified position in linked list
//
void List::deleteNode(Node* current)
{
    --m_size;

    if(current == m_listHead) 
        m_listHead = current->next;
    if(current->prev) 
        current->prev->next = current->next;
    if(current->next) 
       current->next->prev = current->prev;
}


//
// Retrieves a specified node from the list
//
Node* List::retrieveNode(unsigned position)
{
    if(position > (m_size-1) || position < 0)
    {
        cout << "Can't access node; out of list bounds";
        cout << endl;
        cout << endl;

        exit(EXIT_FAILURE);
    }

    Node* current = m_listHead;
    unsigned pos = 0;

    while(current != 0 && pos != position)
    {
        current = current->next;
        ++pos;
    }

    return current;
}

这是堆栈类:

#ifndef stack_H
#define stack_H

#include "linkList.h"


class Stack
{
public:

    //
    // Constructor, copy constructor and destructor to initialize stack 
    // data, copy data and clear up memory, respectively
    //
   Stack() : m_top(0), m_stack(new List()) {}
   Stack(const Stack &rhs);

   ~Stack() { delete [] m_stack; }

    //
    // functionality to determine if stack is empty
    //
    bool isEmpty();

    //
    // methods for pushing data on to stack and for
    // popping data from the stack
    //
    void push(int newValue);
    int  pop();

    //
    // accessor functions for retrieving the value on top of stack
    // and for returning the stack size
    //
    int getTop() const { return m_top->number; }
    int getSize() const { return m_stack->getListSize(); }

    //
    // overloaded assignment operator for copying stack
    //
    Stack& operator=(const Stack &rhs);

private:

    //
    // member data which represent the stack, the top
    // of the stack and the size of the stack
    //
    Node* m_top;
    List* m_stack;
};

#endif

最后,这是堆栈实现

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

using namespace std;

//
// Copy constructor
//
Stack::Stack(const Stack &rhs)
    : m_top(rhs.m_top), m_stack(rhs.m_stack)
{
}

//
// if the Top of stack is zero, return true
//
bool Stack::isEmpty()
{
    if( m_top == 0 ) return true;
    else return false;
}

//
// increment stack pointer, place new value in stack
//
void Stack::push(int newValue)
{
    ++m_top;               
    m_top->number = newValue;   // crashes on this statement
}

//
// if the stack is empty, throw an error message
//
int Stack::pop()
{
    if( isEmpty() )
    {
        cout << "Error: stack underflow" << endl;
        exit(EXIT_FAILURE);
    }

    --m_top;
    return (m_top + 1)->number;

}


Stack& Stack::operator=(const Stack &rhs)
{
    if( this != &rhs )
        delete [] m_stack;

    m_stack = new List();
    m_stack = rhs.m_stack;
    m_top = rhs.m_top;

   return *this;
}

程序在主程序中的这个简单代码后崩溃:

Stack stack;

stack.push(1);

再次,抱歉这里的代码数量。我相信我的问题是Node对象需要重载运算符,以便在将值推送/弹出到堆栈时“递增”或“递减”以创建/删除节点。是这样的吗?另外,我不确定我是否需要Node对象的复制构造函数。这里可能会有更多问题(可能算法不正确?堆栈的复制结构可能不正确?)。有什么想法吗?

5 个答案:

答案 0 :(得分:3)

让我们逐行拍摄您的崩溃场景。 (好,因为它只有2行!)
首先是声明:Stack stack;
这将调用stack-constructor,它会将m_top设置为什么值?

接下来,有一行:stack.push(1);
stack.push的两个陈述都将使用m_top 第一个陈述是++m_top;
考虑到m_top开头的价值,它现在有什么价值?

第二个陈述是m_top->number = newValue;
如果您正确回答了前面关于m_top的问题,那么应该清楚为什么程序在此时崩溃了。如何解决它也应该相对清楚。

答案 1 :(得分:1)

m_top在您的构造函数中设置为0。但...

您的Stack只需要以非常具体的方式装饰您的List。通过简要地查看您的List标题,如果您了解堆栈的工作方式,那么这一切都应该相对容易实现......

您的Stack无需持有“顶部”。它应该根据您的List来实施。推入堆栈应该在列表的前面添加一个新节点,从堆栈弹出应该从列表前面删除一个节点。

答案 2 :(得分:1)

首先,你不能在m_stack(delete [] m_stack)上使用数组删除运算符,因为只有一个对象没有数组(m_stack = new List)。这会导致崩溃。 (实际上我不明白为什么它是动态创建的。)

然后,您需要为List类编写一个正确的赋值运算符和复制构造函数,它将复制节点,还需要一个清理已分配节点的析构函数,但这没什么与你的崩溃有关(但将来很容易引起你)。

崩溃的当前原因,就像其他人所说的那样,当它为null时,Stack尝试访问m_top。

但主要的问题是糟糕的设计会让你以不明确的方式使用List类:/

  • 首先,如果你有一个双向链表,List类也应该跟踪尾指针而不仅仅是头指针。这会让你免于麻烦。
  • 然后,addHead, addTail, insertBefore, insertAfter不应该依赖用户来创建节点,而是在里面创建它们并返回新创建的节点。
  • 同样非常不安全的是nextprev指针被公开,并且可以在List类之外进行更改。我建议你使用make prev和next private并为它们公开一个getter,所以它们无法更改(在这种情况下,List类需要成为Node struct / class的朋友)。

我认为,这些将为您提供良好的开端,如何从头开始重写List和Stack。另外,请留意现在未处理的节点的所有权。

答案 3 :(得分:0)

您在构造函数中将m_top初始化为0(null),然后尝试在push()

中使用它

答案 4 :(得分:0)

最佳方法是一次测试这些类。由于Stack首先依赖于List,调试列表。我假设您可以访问调试器。如果没有,请学习如何使用它。您还需要为List类编写一些测试代码。

祝你好运。