LList需要注意一点就是fence的重新定义,这无非是方便了insert()操作而已,试想,如果fence还指向当前位置的话,那么进行insert操作的时候,当前位置的地址存储在上一个元素的next中,那么要想拿到上一个元素,对于单项链表必须从表头开始一个一个的移动,so 麻烦 !!!于是重新定义 fence使其指向当前位置的上一位置,这样的话上面的问题就解决了,不过又冒出一新的问题,拿第一个元素的上一个怎么处理啊,简单,加一个head节点即可,代表第0个位置,不存值。两中fence定义的图解如下:
原本fence定义:
修正后的Fence定义图:
Insert解析图,注意指针的改动顺序:
remove指针改动解析图:
#include<iostream>
using namespace std;
//定义链表的节点类型
//注意结构性开销
template<class Elem>
/**/class Link{
public:
Elem element;//该节点的值
Link *next;
Link(Elem elemval,Link *nextval = NULL){
element = elemval;
next = nextval;
}
Link(Link *nextval = NULL){
next = nextval;
}
//这两个构造函数仔细一看蛮有意思,两个构造函数
//但是结合默认参数已经包含了所有的四种参数
//传递形式
};
template<class Elem>
class LList{
private:
Link<Elem> *head;
//head指向的是第一个元素的前一个位置,即该位置没有值,
//这样设计是因为fence的定义为当前位置的前一个位置
//fence这样定义是因为方便之后的insert操作(结合指针链表特点think...)
Link<Elem> *tail;
//指向链表的最后一格元素,特点是next一定为NULL
Link<Elem> *fence;
//另一种解释这个意义为:Last element on left
int leftcnt;
int rightcnt;
void init(){ //初始化(在构造函数中调用)
head = tail = fence = new Link<Elem>;
leftcnt = rightcnt = 0;
}
void removeAll(){
while(head!=NULL){
fence = head;
head = head->next;
delete fence;
}
}
public:
LList(){ init();}
~LList(){removeAll();}
void clear(){
removeAll();
init();
}
void setStart(){
fence = head;
rightcnt+=leftcnt;
leftcnt = 0;
}
void setEnd(){
fence = tail;
leftcnt+=rightcnt;
rightcnt = 0;
}
void next(){
//当fence不是tail时才可向下一个移动
//注意,每次对fence修改,同时要对影响到其他
//成员变量的值进行修改
//如leftcnt,rightcnt
if(fence!=tail){
fence = fence->next;
leftcnt++;
rightcnt--;
}
else cout<<"已经是最后不能向后移动了!"<<endl;
}
int leftLength(){return leftcnt;}
int rightLenghth(){return rightcnt;}
bool getValue(Elem &it){
if(rightLength==0)
return false;
//不要忘记fence的定义,指向的是当前元素的上一位置
it = fence->next->element;
return true;
}
//在类外实现的函数
bool insert(Elem item);
bool append(Elem item);
bool remove(Elem &it);
void pre();
bool setPos(int pos);
void print();
bool find(Elem item);
};
template<class Elem>
void LList<Elem>::pre(){
Link<Elem>* temp = head;
while(temp->next!=fence)
temp = temp->next;
fence = temp;
leftcnt--;
rightcnt++;
}
template<class Elem>
bool LList<Elem>::insert(Elem item){
fence->next = new Link<Elem>(item,fence->next);
//fence=fence->next;当前位置即插入的位置,所以fence不用变
if(fence==tail)tail = fence->next;//注意对特殊情况的处理!!!
rightcnt++;//fence指向的是左边最后一个元素,所以是rightcnt加一
return true;
}
template<class Elem>
bool LList<Elem>::append(Elem item){
tail->next = new Link<Elem>(item,NULL);
tail = tail->next;
rightcnt++;
return true;
}
template<class Elem>
bool LList<Elem>::remove(Elem &it){
if(fence->next==NULL)return false;
//此时fence指向tail组后一格元素,但是当前元素为最后元素的
//后一位置,该位置是逻辑上的,实际不存在,所以不能删除
it = fence->next->element;
//记住删去值的信息,以便使用
//fence->next = fence->next->next;
//不建议这样写,因为这样写的话,欲删掉元素的地址即(原fence->next)
//将会丢失,这样在对其地址进行回收或者判断末尾操作的时候将无法进行
//所以先对fence->next保存一下
Link<Elem> *ltemp = fence->next;
fence->next = ltemp->next;
if(ltemp == tail)//如果删除的元素是尾巴,那么得从新给尾巴赋值
tail = fence;
delete ltemp;//回收该内存
rightcnt--;
return true;
}
template<class Elem>
bool LList<Elem>::setPos(int pos){
if(pos<0||pos>rightcnt+leftcnt)
return false;
fence = head;
for(int i=0;i<pos;i++)
fence=fence->next;
rightcnt = rightcnt+leftcnt-pos;
leftcnt = pos;
return true;
}
template<class Elem>
void LList<Elem>::print(){
cout<<"The list Is : < ";
Link<Elem>* temp = head;
while(temp!=fence){
cout<<temp->next->element<<" ";
temp = temp->next;
}
cout<<"| ";
while(temp->next!=NULL){
cout<<temp->next->element<<" ";
temp = temp->next;
}
cout<<">"<<endl;
}
template<class Elem>
bool LList<Elem>::find(Elem item){
if(leftcnt+rightcnt==0)return false;
Link<Elem>* temp = head->next;
while(temp!=NULL){
if(temp->element==item)return true;
temp=temp->next;
}
return false;
}
int main(){
LList<int>list;
list.print();
for(int i=0;i<5;i++)
list.append(i*2);
list.print();
list.next();
list.print();
list.insert(5);
list.print();
int item;
list.remove(item);
cout<<item<<" is removed !"<<endl;
list.print();
list.pre();
list.print();
if(list.find(6))cout<<"6 is in the list !"<<endl;
else cout<<"6 is not in the list!"<<endl;
if(list.find(7))cout<<"7 is in the list !"<<endl;
else cout<<"7 is not in the list !"<<endl;
list.setPos(3);
list.print();
list.setPos(0);
list.print();
return 0;
}