数据结构 List(双链表实现)C++

本文介绍了使用C++实现双链表List的数据结构,强调了双链表在插入和删除操作上的高效性,以及在随机访问上的低效。文章讨论了如何人为实现List的随机访问功能,并对比了两种不同的实现思路,最终给出了代码实现。
摘要由CSDN通过智能技术生成

写在前面:

哈哈哈高产如我(✧◡✧)

简介:

  • 双链表实现的List,相比于数组实现的List,插入和删除效率高,且不会溢出,但随机访问耗时长,且空间利用率较低(因为每个结点除了存data之外,还要存两个指针)。

  • 因为链表本身没有根据下标访问这个功能,但List有,所以要人为地实现这个功能。
    (首先应该知道,基于链表存储数据,应该设置一个“游标指针”——current)
    有两个思路:

  1. 每次current都从头开始遍历,同时开始计数,要定位到第几个位置就数到几的时候停止。
  2. 设置一个整型变量(叫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> &copy);
    //void oprator=(const List<List_entry> &copy);
    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;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值