C++List的模拟实现

list的基本结构

list在库中是一个实现删除插入的一个容器, 其中底层的结构是一个双向的循环链表.
链表中的每一个元素都存储在每一个互不相干的独立结点之中. 每一结点中保存了该结点的前一个元素和后一个元素的地址. 对其进行删除插入的操作的时候, 时间复杂度都是O(1);
list不同的地方就在于其迭代器的实现, 由于List中所存储的都是每一个结点的地址,因此对迭代器进行解引用以及++/–操作是需要进行
list的类结构如下(这里我们都采用泛型编程来实现)

template <class T>
class List{
public:
   //在这里得LsitNode进行明明
   typedef ListNode Nnde;
   typedef LsitNode* pNode; 
   //构造
   Lsit(){
   _head=new Node;
   _head->_next=_head;
   _head->_prev=_head;
}
~List(){
if (_head){
   pNode cur = _head->_next;
   while (cur != _head){
    //1.先保存当前结点的下一个结点
    //2.删除当前结点
    //将保存的下一个结点更新成为当前的结点
    pNode next = cur->_next;
    delete cur;
    cur = next;
   }
   delete _head;
   _head = nullptr;
  }
}
private:
   //链表中只有一个头结点
   LsitNode* _head
}

因为list中是由每一个结点链接而来的, 因此这里也需要对每一个结点进行定义

template <class T>
struct ListNode{
  //实现泛型的LsitNode的构造
  LsitNode(const T& val=T())
  :_data(val);
  ,_next(nullptr)
  ,_prev(nullptr)
  {}
  T  _data;
  LiatNode<T>*  _next;
  ListNode<T>*  _prev;
}

以上就是list的最基本的底层结构,下面来实现一些其他的基本接口
头插

void pushfront(const T& val){
pNode newnode=new Node(val);
  pNode cur=_head->_next;
  newNode->_next = _head->_next;
  _head->_next->_prev = newNode;
  _head->_next = newNode;
  newNode->_prev = _head;
}

头删

void PopFront(){
  pNode cur = _head->_next;
  _head->_next = cur->_next;
  cur->_next->_prev = _head;
  delete cur;
 }

尾插

//尾插
 void PushBuck(const T& val){
  //申请空间建立心结点
  pNode newNode = new Node(val);
  pNode cur = _head->_prev;
  cur->_next = newNode;
  newNode->_next = _head;
  _head->_prev = newNode;
  newNode->_prev = cur;
 }

尾删

//尾插
 void PushBuck(const T& val){
  //申请空间建立心结点
  pNode newNode = new Node(val);
  pNode cur = _head->_prev;
  cur->_next = newNode;
  newNode->_next = _head;
  _head->_prev = newNode;
  newNode->_prev = cur;
 }

注意: 这里是利用最基本的逻辑来实现的插入删除操作, 在实现了insert之后就可以利用insert函数实现以上四个操作
insert(在pos位置插入)
注意:这里的参数传入的是一个迭代器的参数

void Insert(iterator pos, const T& val){
  pNode newNode = new Node(val);
  pNode cur = pos._node;
  newNode->_next = cur;
  newNode->_prev = cur->_prev;
  cur->_prev->_next = newNode;
  cur->_prev = newNode;
 }

删除pos位置处的结点,并且返回后一个结点的值

iterator Erase(iterator pos){
  if (pos != end()){
   pNode cur = pos._node;
   pNode next = cur->_next;
   pNode prev = cur->_prev;
   prev->_next = next;
   next->_prev = prev;
   delete cur;
   pos = iterator(next);
  }
  return pos;
 }

判空

bool Empty() const {
  return (_head->_next == _head);
 }

获取Lsit的长度

size_t Size()const {
  size_t i = 0;
   pNode cur = _head->_next;
   while (cur != _head){
    cur = cur->_next;
    ++i;
  }
   return i;
 }

清空List

void Clear(){
  if (Empty()){
   return;
  }
  pNode cur = _head->_next;
  while (cur != _head){
   _head->_next = cur->_next;
   delete cur;
   cur = _head->_next;
  }
  _head->_next = _head;
  _head->_prev = _head;
 }

拷贝构造以及赋值运算符的重载

List(const List<T>& lst){
  _head = new Node;
  _head->_next = _head;
  _head->_prev = _head;
  auto lit = lst.begin();
  while (lit != lst.end()){
   PushBuck(*lst);
  }
 }
 List<T>& operator=(const List<T>& lst){
  swap(_head, lst._head);
  return *this;
 }

迭代器的头和尾

iterator begin(){
  return iterator(_head->_next);
 }
 iterator end(){
  return  iterator(_head);
 }

迭代器的封装
这里一共定义了三个模板参数,目的是为了针对解引用以及++操作时让代码看起来不繁琐

template <class T,class Ref,class Ptr>
struct ListInterator{
 //在迭代器中封一个结点
 typedef ListInterator<T,T&,T*> Self;
 ListNode<T>* _node;
 ListInterator( ListNode<T>* node)
  :_node(node)
 {}
 //解引用
 Ref operator* (){
  return _node->_data;
 }
 Ptr operator-> (){
  return &(_node->_data);
 }
 bool operator!=(const Self& lit){
  if (_node != lit._node){
   return true;
  }
  else{
   return false;
  }
 }
 bool operator==(const Self& lit){
  return _node == lit._node;
 }
 //前置++
 Self& operator++(){
  _node = _node->_next;
  return *this;
 }
 //后置++
 Self operator++(int){
  Self tmp(*this);
  _node = _node->_next;
  return tmp;
 }
};

const迭代器的实现只需要在List的类中就行重命名是进行修改

 typedef ListInterator<T,T&,T*> iterator;
 typedef ListInterator<T, const T&,const T*> const_iterator;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值