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

发布于 2024-12-09 01:33:57 字数 5807 浏览 1 评论 0原文

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

依赖类,链表

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

OK making progress here. My question is now related to copy construction and deep-copy. My stack is currently crashing all the time and I have a feeling that it is doing so because the class it is dependent on doesn't allow copy construction and operator overloading. But anyway here is my code (I apologize for the amount of code but it is probably necessary to understand where i am failing):

The dependent class, 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

Implementation of 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;
}

Here is the stack class:

#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

And finally, here is the stack implementation

#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;
}

Program crashes after this simple code in the main program:

Stack stack;

stack.push(1);

Again, sorry for the amount of code here. I believe my problem here is that the Node object needs overloaded operators in order to "increment" or "decrement" to create/delete a node when a value is being pushed/popped to the stack. Is this the case? Also, I am not sure if I need a copy constructor or not for the Node object. There could be many more problems here (maybe the algorithms are incorrect? maybe copy construction is incorrect for stack?). Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

空名 2024-12-16 01:33:58

让我们逐行分析一下崩溃场景。 (很好,因为它只有 2 行!)
首先是语句:Stack stack;
这将调用堆栈构造函数,它将 m_top 设置为什么值?

接下来,有一行:stack.push(1);< /代码>
stack.push 的两条语句都会使用 m_top
第一条语句是++m_top;
给定m_top开始时的值,现在它的值是什么?

第二个语句是m_top->number = newValue;
如果您正确回答了前面有关 m_top 的问题,那么应该清楚程序此时崩溃的原因。如何修复也应该比较清楚了。

Lets take your crashing scenario line-by-line. (good, cause it only has 2 lines!)
First the statement: Stack stack;
This will call the stack-constructor, which will set m_top to what value?

Next, there's the line: stack.push(1);
The two statements of stack.push will both use m_top.
The first statement is ++m_top;
Given what value m_top started with, what value will it have now?

The second statement is m_top->number = newValue;
If you answered the previous questions about m_top correctly, it should be clear why the program is crashing at this point. It should also be relatively clear how to fix it.

迷你仙 2024-12-16 01:33:58

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

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

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

m_top is set to 0 in your constructor. But...

Your Stack just needs to decorate your List in a very specific manner. From looking briefly at your List header, it all should be relatively easy to implement, if you understand how a stack works...

Your Stack doesn't need to hold a "top". It should be implemented in terms of your List. Pushing onto the stack should add a new node at the front of your list, and popping from the stack should remove a node from the front of your list.

夏有森光若流苏 2024-12-16 01:33:58

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

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

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

但主要问题是糟糕的设计,这使得您以一种不明确的方式使用 List 类:/

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

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

First of all, you can't use the array delete operator on m_stack (delete [] m_stack) because there is only a single object there not an array (m_stack = new List). This will cause a crash. (Actually I don't see why it's created dynamically.)

Then, you will need to write a proper assignment operator and copy constructor for your List class, which will copy the nodes, and also a destructor which clean up the allocated nodes, but this has nothing to do with your crash (but will easily cause you in the future).

The current cause of the crash, is like the others said, that Stack tries access m_top while it's being null.

But the main problem is bad design which makes you use the List class in an unclear way :/

  • First, if you have a two-way linked list, the List class should also track the tail pointer not just the head pointer. This will free you from a lot a head-aches.
  • Then, addHead, addTail, insertBefore, insertAfter should not rely on the user to create the nodes, but create them inside the functions and return the newly created node.
  • Also it is very unsafe that the next and prev pointers are exposed and can be changed outside the List class. I suggest you the make prev and next private and expose a getter for them, so they could not be changed (List class will need to be friend of the Node struct/class in this case).

I think, these will give you good start how to re-write List and Stack from scratch. Also, keep an eye out for the ownership of the nodes which is not handled now.

a√萤火虫的光℡ 2024-12-16 01:33:58

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

You initialize m_top to 0 (null) in the constructor then try and use it in push()

江湖正好 2024-12-16 01:33:58

最好的方法是一次测试这些类。由于Stack依赖于List,所以先调试list。我假设您有权访问调试器。如果没有,就买一个并学习如何使用它。您还需要为 List 类编写一些测试代码。

祝你好运。

Best approach is to test these classes one at a time. Since Stack depends on List, debug list first. I'm assuming that you have a access to a debugger. If not get one and learn how to use it. You also need to write some test code for the List class.

Good luck.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文