[英]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类:/
addHead, addTail, insertBefore, insertAfter
不应依赖用户来创建节点,而应在函数内部创建它们并返回新创建的节点。 next
和prev
指针并且可以在List类之外进行更改也是非常不安全的。 我建议您将make prev和next私有,并为它们公开一个getter,这样就不能更改它们(在这种情况下,List类需要成为Node struct / class的朋友)。 我认为,这些将为您重新开始如何重新编写List和Stack提供一个良好的开端。 另外,请注意尚未处理的节点的所有权。
您在构造函数m_top
初始化为0
(空),然后尝试在push()
使用它
最好的方法是一次测试这些课程。 由于堆栈取决于列表,因此请首先调试列表。 我假设您可以访问调试器。 如果没有得到,并学习如何使用它。 您还需要为List类编写一些测试代码。
祝好运。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.