/*
Linked List exercise
*/
#include <iostream>
#include <exception>
#include <string>
using namespace std;
class node{
public:
node * next;
int * data;
node(const int i){
data = new int;
*data = i;
}
node& operator=(node n){
*data = *(n.data);
}
~node(){
delete data;
}
};
class linkedList{
public:
node * head;
node * tail;
int nodeCount;
linkedList(){
head = NULL;
tail = NULL;
}
~linkedList(){
while (head){
node* t = head->next;
delete head;
if (t) head = t;
}
}
void add(node * n){
if (!head) {
head = n;
head->next = NULL;
tail = head;
nodeCount = 0;
}else {
node * t = head;
while (t->next) t = t->next;
t->next = n;
n->next = NULL;
nodeCount++;
}
}
node * operator[](const int &i){
if ((i >= 0) && (i < nodeCount)) throw new exception("ERROR: Invalid index on linked list.", -1);
node *t = head;
for (int x = i; x < nodeCount; x++) t = t->next;
return t;
}
void print(){
if (!head) return;
node * t = head;
string collection;
cout << "[";
int c = 0;
if (!t->next) cout << *(t->data);
else while (t->next){
cout << *(t->data);
c++;
if (t->next) t = t->next;
if (c < nodeCount) cout << ", ";
}
cout << "]" << endl;
}
};
int main (const int & argc, const char * argv[]){
try{
linkedList * myList = new linkedList;
for (int x = 0; x < 10; x++) myList->add(new node(x));
myList->print();
}catch(exception &ex){
cout << ex.what() << endl;
return -1;
}
return 0;
}
答案 0 :(得分:7)
不需要数据作为指针。
使用ctor-initializer列表,最好是const-correctness和exception safety。你的构造函数都不需要在体内有任何代码。
您的linkedList构造函数未初始化nodeCount。
您没有使用列表的尾指针来表示任何事情。如果你保持最新状态,它可以节省你在非空的添加情况下扫描整个列表。
索引(operator [])在链表上支持是一件不寻常的事情。 OTOH你还没有删除功能。
operator []不应该通过引用获取其参数。只有大型结构需要通过const引用传递,像int这样的小类型应该只通过值传递。
现在,如果添加失败,指向新节点()的指针会泄漏。 (但我实际上并没有看到添加失败的方法,除非列表链接被破坏。)
您应该在节点上定义私有复制构造函数,以防止数据双重释放。每次定义operator =和析构函数时,您还应该定义或删除复制构造函数(三个规则)。您还应该在linkedList上定义私有拷贝构造函数和赋值运算符,以防止双重释放。
不使用print函数中的变量字符串集合。 print()中的变量t应该是指向const的指针。 print本身应该是const成员函数。
答案 1 :(得分:4)
/*
Linked List exercise
*/
class node {
public:
node * next;
int * data;
data
并不一定需要成为一个指针(除非你的课堂作业必须是这样)。您可以将其更改为int
,然后将引用从*(t->data)
更改为仅t->data
。同样,您不需要在ctor / dtor中使用new
和delete
。
node(const int i) {
data = new int;
*data = i;
}
node& operator=(node n) {
*data = *(n.data);
}
~node() {
delete data;
}
};
class linkedList {
public:
node * head;
node * tail;
int nodeCount;
linkedList() {
head = NULL;
tail = NULL;
您应该在此处初始化所有数据成员。除非您在此处设置为零,否则nodeCount
将具有一些随机值。
}
~linkedList() {
while (head) {
node* t = head->next;
delete head;
if (t)
head = t;
这看起来像个错误。您需要始终分配head = t
,即使t为NULL
,否则您的循环将不会终止(但多次删除同一节点可能会导致异常)。
}
}
void add(node * n) {
if (!head) {
head = n;
head->next = NULL;
tail = head;
nodeCount = 0;
我认为整个if
声明是不必要的。当链表为空时,两个分支都执行相同的操作,因此您可以始终使用第二个( else )分支。
此外,将nodeCount
设置为0
似乎是一个错误;不应该是1
?
} else {
node * t = head;
while (t->next)
t = t->next;
t->next = n;
n->next = NULL;
nodeCount++;
}
}
node * operator[](const int &i) {
一个小问题,但const int &
论证并没有任何意义。你只是传递int
类型而没有获得任何好处。
if ((i >= 0) && (i < nodeCount))
throw new exception("ERROR: Invalid index on linked list.", -1);
上述情况向我看来;你总是会抛出有效参数的异常。
node *t = head;
for (int x = i; x < nodeCount; x++)
t = t->next;
上面的循环对我来说似乎有点怀疑。如果i
是您想要的节点从零开始的索引,那么您的计数器不应该从0
转到i-1
吗?
return t;
}
void print() {
if (!head)
return;
同样,你应该让这个方法工作,而不必防止空列表。我希望有一个空列表可以打印[]
之类的内容,但是上面有保护代码,你什么都不打印。
node * t = head;
string collection;
int c = 0;
cout << "[";
if (!t->next) {
cout << *(t->data);
与上述其他条件一样,我认为上面的分支是不必要的。第二个( else )分支应该处理NULL
情况。
} else {
while (t->next) {
我认为你想要while (t)
而不是while (t->next)
cout << *(t->data);
c++;
if (t->next)
t = t->next;
我认为这是一个像之前的错误。您总是分配't = t-&gt; next',否则您的循环将不会终止。
if (c < nodeCount)
cout << ", ";
}
}
cout << "]" << endl;
}
};
int main (const int & argc, const char * argv[]) { // const int& ?
const int &
再次......
try {
linkedList * myList = new linkedList;
for (int x = 0; x < 10; x++)
myList->add(new node(x));
myList->print();
} catch(exception &ex) {
cout << ex.what() << endl;
return -1;
}
家庭作业可能很好,但抓住每一个可能的例外(正如你上面所做的那样)可能在这里没有增加太多价值,而且通常被认为是不好的做法。
如果省略上面的try / catch内容,我怀疑每当程序以异常终止时,编译器提供的默认顶级异常处理程序将转储异常并堆栈跟踪信息(取决于你的编译器)。
return 0;
}
答案 2 :(得分:0)
if ((i >= 0) && (i < nodeCount)) throw new exception("ERROR: Invalid index on linked list.", -1);
该行应为:
if( i < 0 || i >= nodeCount ) throw...
add方法也存在问题:
void add(node * n){
if (!head) {
head = n;
head->next = NULL;
tail = head;
nodeCount = 0;
}else {
node * t = head;
while (t->next) t = t->next;
t->next = n;
n->next = NULL;
nodeCount++;
}
}
对于一个添加后的第一个节点计数将为0,对于另一个,您正在进行搜索以插入链接列表...人们期望的操作是O(1)。
更典型的实现是:
void add( node* n ) {
node* old_head = head;
head = n;
head->next = old_head;
++nodeCount;
if( old_head == NULL )
tail = head
}
答案 3 :(得分:0)
1)您可以使用data = new int(i)
初始化字段。
2)您在operator [] if ((i >= 0) && (i < nodeCount))
中创建了一个错误的条件,它应该被反转,如if ((i < 0) || (i >= nodeCount))