繁体   English   中英

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

[英]C++ stack implementation (homework) PT. II

确定在这里取得进展。 我的问题现在与复制构造和深复制有关。 我的堆栈当前一直在崩溃,我有一种感觉,因为它所依赖的类不允许复制构造和操作符重载。 但是无论如何这是我的代码(我为代码量表示歉意,但可能有必要了解我的失败之处):

依赖类,链表

#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对象是否需要复制构造函数。 这里可能还有更多问题(也许算法不正确?也许堆栈的拷贝构造不正确?)。 有任何想法吗?

让我们逐行处理崩溃的情况。 (很好,因为它只有两行!)
首先声明: Stack stack;
这将调用堆栈构造函数,它将m_top设置为什么值?

接下来是一行: stack.push(1);
stack.push的两个语句stack.push将使用m_top
第一条语句是++m_top;
给定m_top最初的值是m_top ,现在它将具有什么值?

第二条语句是m_top->number = newValue;
如果您正确回答了有关m_top的先前问题,那么应该清楚为什么程序此时会崩溃。 还应该相对清楚如何解决它。

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

您的Stack仅需要以非常特定的方式装饰List 如果您了解堆栈的工作原理,那么从简短地查看List头开始,这一切都应该相对容易实现...

您的Stack不需要保持“顶部”。 应该根据您的List来实现。 推入堆栈应在列表的前面添加一个新节点,而从堆栈弹出则应从列表的前面删除一个节点。

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

然后,您将需要为List类编写一个适当的赋值运算符并复制构造函数,以复制节点,并使用析构函数清理分配的节点,但这与崩溃无关(但很容易导致崩溃将来的您)。

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

但是主要的问题是不良的设计,这使您无法清楚地使用List类:/

  • 首先,如果您有双向链接列表,则List类还应该跟踪尾指针,而不仅仅是头指针。 这将使您免于头痛。
  • 然后, addHead, addTail, insertBefore, insertAfter不应依赖用户来创建节点,而应在函数内部创建它们并返回新创建的节点。
  • 同样,公开nextprev指针并且可以在List类之外进行更改也是非常不安全的。 我建议您将make prev和next私有,并为它们公开一个getter,这样就不能更改它们(在这种情况下,List类需要成为Node struct / class的朋友)。

我认为,这些将为您重新开始如何重新编写List和Stack提供一个良好的开端。 另外,请注意尚未处理的节点的所有权。

您在构造函数m_top初始化为0 (空),然后尝试在push()使用它

最好的方法是一次测试这些课程。 由于堆栈取决于列表,因此请首先调试列表。 我假设您可以访问调试器。 如果没有得到,并学习如何使用它。 您还需要为List类编写一些测试代码。

祝好运。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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