写在前面:
哈哈哈高产如我(✧◡✧)
简介:
-
双链表实现的List,相比于数组实现的List,插入和删除效率高,且不会溢出,但随机访问耗时长,且空间利用率较低(因为每个结点除了存data之外,还要存两个指针)。
-
因为链表本身没有根据下标访问这个功能,但List有,所以要人为地实现这个功能。
(首先应该知道,基于链表存储数据,应该设置一个“游标指针”——current)
有两个思路:
- 每次current都从头开始遍历,同时开始计数,要定位到第几个位置就数到几的时候停止。
- 设置一个整型变量(叫current_position),记录当前current指向的位置(相当于数组的下标)。
显然,根据空间局部性,即“被引用过一次的存储器,很有可能在不久的将来引用其附近临近的存储器”,第二个思路的效率更高。
代码:
定义结点:
template <class Node_entry>
struct Node{
//data members
Node_entry entry;
Node<Node_entry> *next;
Node<Node_entry> *prev;
//constructors
Node();
Node(Node_entry the_entry, Node<Node_entry> *link_prev, Node<Node_entry> *link_next);
};
template<class Node_entry>
Node<Node_entry>::Node(){
entry=-1;
prev=NULL;
next=NULL;
}
template<class Node_entry>
Node<Node_entry>::Node(Node_entry the_entry, Node<Node_entry> *link_prev, Node<Node_entry> *link_next)
{
entry=the_entry;
prev=link_prev;
next=link_next;
}
定义List:
为了实现随机访问功能,定义了一个函数叫set_position,是这个数据结构不可或缺的一个函数。
traverse(遍历)函数用到了函数指针。
其他函数详解见注释。
template <class List_entry>
class List{
public:
List();
//~List();
List(const List<List_entry> ©);
//void oprator=(const List<List_entry> ©);
bool empty()const;
bool full()const;
int size()const;
void clear();
void print_the_list();
void traverse(void(*visit)(List_entry &));
Error_code insert(int position, const List_entry &x);
Error_code remove(int position, List_entry &x);
Error_code retrieve(int position, List_entry &x);
Error_code replace(int position, List_entry &x)const;
protected:
//Data members for the doubly-linked list implementation follow:
int count;
Node<List_entry> *head=new Node<List_entry>();
mutable int current_position;
mutable Node<List_entry> *current;
//The auxiliary function to locate list position follows:
void set_position(int position)const;
};
template <class List_entry>
void List<List_entry>::set_position(int position)const
{
if(current_position<position)
for(;current_position!=position;current_position++)
{
if(current->next!=NULL)
current=current->next;
else break;
}
else
for(;current_position!=position;current_position--)
{
if(current->prev!=NULL)
current=current->prev;
else break;
}
}
template <class List_entry>
List<List_entry>::List(){
count=0;
current_position=0;
current=NULL;
}
template <class List_entry>
bool List<List_entry>::empty()const
{
return count==0;
}
template<class List_entry>
bool List<List_entry>::full()const
{
return false;
}
template<class List_entry>
int List<List_entry>::size()const
{
return count;
}
template<class List_entry>
void List<List_entry>::clear()
{
int x;
if(count!=0){
set_position(0);
for(;current!=NULL;current=current->next){
remove(current_position,x);
}
}
}
template<class List_entry>
void List<List_entry>::traverse(void(*visit)(List_entry &))
{
Node<List_entry>*p=head;
for(;p->next!=NULL;p=p->next)
(*visit)(p->entry);
}
template<class List_entry>
Error_code List<List_entry>::insert(int position,const List_entry &x)
{
if(position>count||position<0){
cout<<"位置有误!"<<endl;
return range_error;
}
if(count==max_list)
return overflow;
if(count==0){
head->entry=x;
}
Node<List_entry> *new_node=NULL,*previous=NULL,*following=NULL;//建立三个指针,增加新结点产生三个新数据,先把这三个数据准备好
/**为new一个新结点做准备,previous是将来的prev,following是将来的next**/
if(position>0){ //插入位置不是队首
set_position(position-1); //current指向插入位置的前一个结点
previous=current; //新结点的prev,是现在的current
following=current->next; //其next是现在的current->next
}
else{ //插入位置是队首
following=head; //新结点的prev是null,next是head
}
/**new一个新结点**/
new_node=new Node<List_entry>(x,previous,following);
if(new_node==NULL)//申请空间失败
{
cout<<"申请空间失败!"<<endl;
return overflow;
}
/**把新结点插入链表**/
if(position==0){ //插入位置是队首
head=new_node;
current_position=0;
current=head;
}
else{ //插入位置不是队首
previous->next=new_node;
new_node->next->prev=new_node;
set_position(position);
}
count++;
return success;
}
template <class List_entry>
Error_code List<List_entry>::remove(int position, List_entry &x)
{
if(position<0||position>=count){
cout<<"位置有误!"<<endl;
return range_error;
}
if(empty())
return underflow;
/**删除结点要改变两个指针,设置两个变量存数据做准备**/
Node<List_entry>*previous,*following;
/**删除结点**/
if(position>0){ //要删除的不是首结点
set_position(position-1);
previous=current;
following=previous->next;
previous->next=following->next;
}
else{ //要删除首节点
following=head;
head=head->next;
current_position=0;
current=head;
}
x=following->entry; //x储存被删除的结点存的数据。
delete following;
count--;
return success;
}
template <class List_entry>
Error_code List<List_entry>::retrieve(int position, List_entry &x)
{
if(position<0||position>=count){
cout<<"位置有误!"<<endl;
return range_error;
}
set_position(position);
x=current->entry;
return success;
}
template<class List_entry>
Error_code List<List_entry>::replace(int position,List_entry &x)const
{
if(position<0||position>=count){
cout<<"位置有误!"<<endl;
return range_error;
}
set_position(position);
current->entry=x;
return success;
}
template<class List_entry>
void print(List_entry &x)
{
cout<<x<<" ";
}
template<class List_entry>
void update(List_entry &x)
{
x*=2;
}