好在这里取得进展。我的问题现在涉及复制构造和深层复制。我的堆栈目前一直在崩溃,我觉得它正在这样做,因为它所依赖的类不允许复制构造和运算符重载。但无论如何这里是我的代码(我为代码量道歉,但可能有必要了解我失败的地方):
依赖类,链表
#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对象的复制构造函数。这里可能会有更多问题(可能算法不正确?堆栈的复制结构可能不正确?)。有什么想法吗?
答案 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类:/
addHead, addTail, insertBefore, insertAfter
不应该依赖用户来创建节点,而是在里面创建它们并返回新创建的节点。next
和prev
指针被公开,并且可以在List类之外进行更改。我建议你使用make prev和next private并为它们公开一个getter,所以它们无法更改(在这种情况下,List类需要成为Node struct / class的朋友)。我认为,这些将为您提供良好的开端,如何从头开始重写List和Stack。另外,请留意现在未处理的节点的所有权。
答案 3 :(得分:0)
您在构造函数中将m_top
初始化为0
(null),然后尝试在push()
答案 4 :(得分:0)
最佳方法是一次测试这些类。由于Stack首先依赖于List,调试列表。我假设您可以访问调试器。如果没有,请学习如何使用它。您还需要为List类编写一些测试代码。
祝你好运。