zoukankan      html  css  js  c++  java
  • C++自己实现list

     C++自己实现list

      前两个博客发表了自己写的stack(栈)和queue(队列),感觉比较简单,今天想试着实现list,结果发现,不是那么容易,感觉自己对STL的底层不是很了解,

    真要自己实现还真的很难,看STL的源代码,那个晕啊...那代码也写得太难理解了,当然跟我不了解有关,但我相信,在将来的某一天我会懂的,你看我的代码也会懂的。

      话说:STL中的list的内部结构就是一个双向链表,这个东东以前还真没有玩过,就凭他用的是双向链表我就不想用他,指针太多,耗资源,当然存在就有他的价值,

    他能快速访问其中的元素。 废话总该少说,代码就该多些。

      有那么一点高兴的是实现双向链表的翻转,其他的没什么了,list还没有实现,由于现在能力有限,新的版本一定会发布的,你就将就着看吧!

    源码
    #include <iostream>
    usingnamespace std;

    template
    <typename T>
    class list
    {
    public :
    list()
    {
    initialize();
    }

    list(
    int count)
    {
    initialize();
    if(count>0)
    {
    for(int i=0;i<count;i++)
    {
    push_front(
    0);
    }
    }
    }

    list(
    int count,T data)
    {
    initialize();
    if(count>0)
    {
    for(int i=0;i<count;i++)
    {
    push_front(data);
    }
    }
    }

    //显示最后一个节点
    T& back()
    {
    checkEmpty();
    return cur->data;
    }

    T
    & back() const
    {
    return back();
    }

    //显示第一个节点
    T& front()
    {
    checkEmpty();
    return head->next->data;
    }

    T
    & front() const
    {
    return front();
    }

    //弹出最后一个节点
    void pop_back()
    {
    checkEmpty();
    cur
    =cur->prev;
    delete cur
    ->next;
    cur
    ->next=NULL;
    --len;
    }

    //弹出第一个节点
    void pop_front()
    {
    checkEmpty();
    node
    * tmp=head->next;
    head
    ->next=tmp->next;
    tmp
    ->prev=head;
    delete tmp;
    --len;
    }

    //前插节点
    void push_front(const T& t)
    {
    node
    * newNode=new node(t);
    head
    ->next=newNode;
    newNode
    ->prev=head;
    ++len;
    }

    //后插节点
    void push_back(const T& t)
    {
    node
    * newNode=new node(t);
    newNode
    ->prev=cur;
    cur
    ->next=newNode;
    cur
    =newNode;
    ++len;
    }

    //删除所有值为t的节点
    void remove(const T& t)
    {
    checkEmpty();
    node
    * tmp=head->next;
    for(int i=0;i<len;i++)
    {
    if(tmp->data!=t)
    {
    tmp
    =tmp->next;
    continue;
    }

    if(tmp->next==NULL)//删除最后一个节点
    {
    cur
    =tmp->prev; //将当前节点指向最后一个节点的前一个节点
    cur->next=NULL;//由于保持当前节点指向最后一个节点,他的下一个节点当然为空
    }else//删除中间节点
    {
    tmp
    ->prev->next=tmp->next; //要删除节点的前一个节点的next指针指向要删除节点的下一个节点
    tmp->next->prev=tmp->prev; //要删除节点的下一个节点的prev指针指向要删除节点的前一个节点
    }
    --len;
    node
    * t=tmp->next;
    delete tmp;
    tmp
    =t;
    }
    }


    //反转链表
    //每次都修改当前节点的前后节点指针
    //最后一个节点的下一个指针指向前一个节点
    void reverse()
    {
    checkEmpty();

    node
    * prev = head;// 上一个节点
    node* pcur = head->next;//当前节点
    node* next;
    while (pcur !=NULL)
    {
    if(!pcur->next)
    {
    pcur
    ->next=prev;//最后一个节点的下一个节点指向前一个节点
    break;
    }

    next
    = pcur->next; //下一个节点

    pcur
    ->next=prev; //修改当前节点的下一个节点
    pcur->prev=next; //修改当前及诶单的上一个节点

    prev
    =pcur; //将当前节点设为上一个节点
    pcur=next; //将下一个节点设为当前节点
    }
    cur
    =head->next; //末节点指向头节点
    head->next=pcur; //头指针指向当前节点,也就是指向翻转之前的末节点
    }

    //排序
    //节点之间直接交换数据,而没有用修改指针指向
    void sort()
    {
    if(empty())
    {
    return;
    }
    node
    *p,*t;
    p
    =head->next;
    T d;
    while(p!=NULL)
    {
    t
    =p;
    while(t!=NULL)
    {
    if(p->data>t->data)
    {
    d
    =p->data;
    p
    ->data=t->data;
    t
    ->data=d;
    }
    t
    =t->next;
    }
    p
    =p->next;
    }
    }


    //链表元素个数
    int size()
    {
    return len;
    }

    void resize(int count)
    {
    resize(count,
    0);
    }

    //重新设置元素
    void resize(int count,T t)
    {
    if(count<0)
    {
    thrownew exception("元素的个数不能小于0!");
    }
    clear();
    //内存是必须释放的
    while(count--)
    {
    push_front(t);
    }
    }

    //清空集合
    void clear()
    {
    if(empty())
    {
    return;
    }
    node
    *tmp=head;
    node
    *t=tmp->next;
    while(t!=NULL)
    {
    tmp
    =t;
    t
    =t->next;
    delete tmp;
    }
    tmp
    =NULL;
    t
    =NULL;

    cur
    =head;//当前节点指向头指针
    }


    //链表是否为空
    bool empty() const
    {
    return len==0;
    }

    //判断链表是否为空
    void checkEmpty()
    {
    if(empty())
    {
    thrownew exception("集合中没有元素!");
    }
    }


    private :
    typedef
    struct node1
    {
    node1
    *prev,*next;
    T data;
    node1(T t):data(t),prev(NULL),next(NULL){}
    }node;

    node
    * head;//头节点
    node* cur; //当前节点,指向末节点
    int len; //节点个数

    void initialize()
    {
    cur
    =head=new node(-1);
    len
    =0;
    }
    };

    作者:陈太汉

  • 相关阅读:
    Linked List Cycle leetcode java (链表检测环)
    Remove Duplicates from Sorted List II leetcode java
    Remove Duplicates from Sorted List leetcode java
    Merge Two Sorted Lists leetcode java
    Swap Nodes in Pairs leetcode java
    Median of Two Sorted Array leetcode java
    阿里云最便宜的四种域名注册
    nohup和&后台运行,进程查看及终止
    ipv6转ipv4 NAT64与DNS64基本原理概述
    ros使用pppoe拨号获取ipv6,并且下发IPV6的dns到客户机win7
  • 原文地址:https://www.cnblogs.com/hlxs/p/2113178.html
Copyright © 2011-2022 走看看