本来链表的文件早写好了,无奈老师一道链表倒置的题着实伤了下脑筋,使用标准思路却忘了我设置了头节点,一个小细节导致程序老是处于崩溃状态,一番调试后终于调试成功,故在此分享下想关心得。
Link类头文件
#ifndef LINK_H_
#define LINK_H_
#include<iostream>
template<class Elem>
class Link
{
public:
Elem element;
Link* next;
Link(const Elem& elemval, Link* nextval = NULL)
{
element = elemval;
next = nextval;
}
Link(Link* nextval = NULL)
{
next = nextval;
}
};
#endif
link类方法实现
#include"acctlist.h"
#include<iostream>
#include"Link.h"
using namespace std;
template<class Elem>
class Llist: public List<Elem>{
private:
Link<Elem> *head;
Link<Elem> *tail;
Link<Elem> *fence;
int leftcnt,rightcnt;
void init()
{
fence = head = tail = new Link<Elem>;
leftcnt = rightcnt = 0;
}
void removeall()
{
while(head != NULL)
{
fence = head;
head= head -> next;
delete fence;
}
}
public:
Llist(int size)
{
init();
}
~Llist()
{
removeall();
}
void clear()
{
removeall();
init();
}
bool insert(const Elem& item)
{
fence -> next = new Link<Elem>(item,fence -> next);
if(tail == fence)
tail = fence ->next;
rightcnt++;
return true;
}
bool append(const Elem& item)
{
tail = tail -> next = new Link<Elem>(item,NULL);
rightcnt++;
return true;
}
bool remove(Elem& it)
{
if(fence -> next == NULL)
return false;
it = fence -> next -> element;
Link<Elem> *Itemp = fence -> next;
fence -> next = Itemp ->next;
if(tail == Itemp)
tail = fence;
delete Itemp;
rightcnt--;
return true;
}
void setStart()
{
fence = head;
rightcnt += leftcnt;
leftcnt = 0;
}
void setEnd()
{
fence = tail;
leftcnt += rightcnt;
rightcnt = 0;
}
void prev()
{
Link<Elem> *temp = head;
if(fence == head)
return ;
while(temp -> next != fence)
temp = temp -> next;
fence = temp;
leftcnt--;
rightcnt++;
}
void next()
{
if( fence != tail)
{
fence = fence -> next;
rightcnt--;
leftcnt++;
}
}
int leftLength() const
{
return leftcnt;
}
int rightLength() const
{
return rightcnt;
}
bool setPos(int pos)
{
if((pos<0) || (pos > (rightcnt+leftcnt)))
return false;
setStart();
for(int i = 0;i<pos;i++)
next();
return true;
}
bool getValue(Elem & it) const
{
if(rightLength() == 0)
return false;
it = fence -> next -> element;
return true;
}
void reverse()
{
cout << "Now begin the reverse the list" << endl;
if(head -> next && head -> next -> next) {//不为空表或者单节点
Link<Elem>* p = head -> next;
Link<Elem>* r = head -> next -> next;
Link<Elem>* temp = p;
p -> next = NULL;
tail = p ;
while(r) {
p = r ;
r = r -> next ;
p -> next = temp ;
temp = p ;
}
head -> next = temp ;
}
}
void print() const
{
Link<Elem>* temp = head;
cout << " < ";
while(temp != fence)
{
cout << temp -> next -> element << " ";
temp = temp -> next;
}
cout << " | ";
while(temp -> next != NULL )
{
cout << temp -> next -> element <<" ";
temp = temp -> next;
}
cout << ">\n";
}
};
这个头文件中仍然写了很多内联函数,供学习调试方便,以后仍然会按照常规的方法重写。同时大家可以看到reverse()这个函数的代码风格和其他的函数不一样,的确,这个函数是我后来添加的,使用了DOOM3的源码当中的变量声明风格与紧凑的写法,虽然当前感觉有些不伦不类,不过还在继续思考如何写的更好看,以便写出简易易懂的代码方便自己调试。同时在写reverse函数的时候原本以为两个link指针即可搞定,结果忽略了我使用的不带参数的头节点,结构第一次测试逆置功能的时候缺失了首尾元素,所以还是使用了三个link指针才搞定。
测试代码
#include<iostream>
#include"list_link.h"
using namespace std;
enum{clear,insert,append,remove11,setStart,setEnd,prev,next,leftLength,rightLength,
setPos,reverse};
int main()
{
int op;
int temp;
Llist<int> L1(10);
cout << "Please entert the op code" << endl;
cout << "0.clear" << endl;
cout << "1.insert" << endl;
cout << "2.append" << endl;
cout << "3.remove" << endl;
cout << "4.setStart" << endl;
cout << "5.setEnd" << endl;
cout << "6.prev" << endl;
cout << "7.next" << endl;
cout << "8.leftLength" << endl;
cout << "9.rightLength" << endl;
cout << "10.setPos" << endl;
cout << "11.reverse" << endl;
cout << "Please enter the op code(12 to quit)" << endl;
cin >> op ;
while( op != 12 ) {
switch( op ) {
case clear: L1.clear();
L1.print();
break;
case insert: cout << "please enter the number you want to insert:" << endl ;
cin >> temp ;
L1.insert(temp) ;
L1.print() ;
break;
case append: cout << "Please enter the number you want to append:" << endl ;
cin >> temp ;
L1.append(temp) ;
L1.print() ;
break;
case remove11: cout << "Now the list has been removed " << endl ;
L1.remove(temp);
L1.print();
break;
case setStart: cout << "Now set the start " << endl ;
L1.setStart() ;
L1.print() ;
break;
case setEnd: cout << "Now set the end " << endl ;
L1.setEnd() ;
L1.print() ;
break;
case prev: cout << "check the prev " << endl ;
L1.prev() ;
L1.print() ;
break;
case next: cout << "check the next " << endl ;
L1.next() ;
L1.print() ;
break;
case leftLength: cout << "Now the leftLength is " <<
L1.leftLength() << endl ;
break;
case rightLength: cout << "Now the rightLength is " <<
L1.rightLength() << endl ;
break;
case setPos: cout << "set the pos is "<< endl ;
L1.setPos(3) ;
L1.print() ;
break;
case reverse: cout << "Now reverse " << endl ;
L1.reverse() ;
L1.print() ;
break;
}
cout<<"Please enter the op code:";
cin >> op;
}
cout << "thanks for using" << endl ;
}
这次的测试代码稍微人性化了一点点,复制粘贴后的代码排列略乱,我就没有调了,毕竟这样的测试代码以后会很少写了。
测试结果