没想到我的第一个数据结构程序竟然写了3个礼拜多,无聊的电工实习和更无聊的期中考试耽误我不少时间,编写过程中的困难也大大超出了我的预计。以下是我写的代码,其中肯定有很多不妥的矛盾的地方,希望可以得到指正。
// LinkList.h
#ifndef LINKLIST_H #define LINKLIST_H
template
< class T >
struct
Node ...
{ T coef; T exp; Node < T > * next; }
; template < class T >
class
LinkList ...
{ public : LinkList(); LinkList(T a[][ 2 ], int n); ~ LinkList(); void Insert(T a,T b, int loc); void Delete( int loc); void Print(); LinkList < T > operator + (LinkList < T > & l2); LinkList < T > operator * (LinkList < T > & l2); private : Node < T > * first; }
; #endif
// LinkList.cpp
#include " LinkList.h "
template
< class T >
LinkList
< T >
::LinkList() ...
{ first = new Node < T > ; first -> next = NULL; }
template
< class T >
LinkList
< T > ::LinkList(T a[][ 2 ], int
n) ...
{ first = new Node < T > ; first -> next = NULL; for ( int i = 1 ;i <= n;i ++ ) Insert(a[i - 1 ][ 0 ],a[i - 1 ][ 1 ],i); }
template
< class T >
LinkList
< T > :: ~
LinkList() ...
{ // }
template
< class T >
void LinkList < T > ::Insert(T a,T b, int
loc) ...
{ Node < T > * temp; temp = new Node < T > ; temp -> coef = a; temp -> exp = b; Node < T > * p = first; for ( int i = 1 ;i < loc;i ++ ) p = p -> next; temp -> next = p -> next; p -> next = temp; }
template
< class T >
void LinkList < T > ::Delete( int
loc) ...
{ Node < T > * p = first; for ( int i = 1 ;i < loc;i ++ ) p = p -> next; Node < T > * q = p -> next; p -> next = p -> next -> next; delete q; }
template
< class T >
void LinkList < T >
::Print() ...
{ Node < T > * p = first -> next; while (p) ... { cout << p -> coef << " x^ " << p -> exp << " " ; p = p -> next; } cout<< endl; }
template
< class T >
LinkList
< T > LinkList < T > :: operator + (LinkList < T > &
l2) ...
{ LinkList < T > sum; Node < T > * p = first -> next; Node < T > * q = l2.first -> next; Node < T > * r = sum.first; int loc = 1 ; while (p && q) ... { if (p -> exp < q -> exp) ... { sum.Insert(p -> coef,p -> exp,loc); loc ++ ; p = p -> next; } else if (p -> exp > q -> exp) ... { sum.Insert(q -> coef,q -> exp,loc); loc ++ ; q = q -> next; } else ... { if (p -> coef + q -> coef == 0 ) ... { p = p -> next; q = q -> next; } else ... { sum.Insert(p -> coef + q -> coef,p -> exp,loc); p = p -> next; q = q -> next; loc ++ ; } } } while (p) ... { sum.Insert(p -> coef,p -> exp,loc); p = p -> next; loc ++ ; } while (q) ... { sum.Insert(q -> coef,q -> exp,loc); q = q -> next; loc ++ ; } return sum; }
template
< class T >
LinkList
< T > LinkList < T > :: operator * (LinkList < T > &
l2) ...
{ LinkList < T > sum; Node < T > * p = first -> next; Node < T > * q; int loc = 1 ; while (p) ... { LinkList < T > * temp = new LinkList < T > ; q = l2.first -> next; while (q) ... { temp -> Insert(p -> coef * q -> coef,p -> exp + q -> exp,loc); loc ++ ; q = q -> next; } sum= sum + ( * temp); delete temp; loc = 1 ; p = p -> next; } return sum; }
上述代码中各项的实现方法我就不做具体分析了,很多书上都有而且肯定比我分析得好,有看不懂的地方也可以问我。这里要讲的是一些容易出错的地方,相信很多人在写链表时也和我一样遇到过许多莫名的错误,甚至让人觉得是电脑的问题。但是电脑毕竟是很按部就班的机器,绝大多数错误都源于代码中的bug。这些错误的代码的共同点是让人觉得理所当然,当然也就很难发现,发现了才意识到是多么愚蠢的错误。我曾一度这样定义插入函数:
template < class T >
void LinkList < T > ::Insert(T a,T b, int
loc) ...
{ Node < T > * temp; temp -> coef = a; temp -> exp = b; Node < T > * p = first; for ( int i = 1 ;i < loc;i ++ ) p = p -> next; temp -> next = p -> next; p -> next = temp; }
这段代码看起来貌似没有什么错误,其实在声明*temp时并没有为它分配空间,导致当程序执行到 temp->coef=a 时,没有一个可以存放a的值的空间。注意了,如果已有另一个Node<T>型的指针p,那么 Node<T> *temp; temp=p; 自然是合法的,因为系统会把temp指向p所指向的数据空间。将这两种情况放在一起就会发现很容易混淆,而像这样的问题编译器是不会通知你的。由于在构造函数中调用了插入函数,使得我根本无法定义一个链表,最后通过断点步进才找到了错误的地方,在此要顺便感谢一下Samson的帮助。其实在写程序的过程中像这样的低级错误在所难免,所以不应忽视一下细节上的问题。
关于这个程序的分析只能暂时写到这里,程序中还有一些让人困惑的地方目前我还不能做出明确的解释(比如链表的析构函数为什么为空),只能以后再做补充。最后要说明一下在这个程序中并没有使用迭代器类,关于迭代器会在我以后的文章中做初步的讨论。