内置迭代器的双向循环链表

有些日子没有写文章了.

最近重新看了一下数据结构和算法设计.写了个双向循环链表,这玩意儿倒不难.

既然要适应多种类型的需求,当然要用类模板了...

  1. #ifndef LIST_H
  2. #define LIST_H
  3. template <typename T>
  4. class list
  5. {
  6.     private:
  7.         struct Node
  8.         {
  9.             Node(){prev = next = NULL;}
  10.             Node(const T&e,Node *p = NULL,Node *n = NULL):prev(p),next(n),data(e){}
  11.             Node *prev;
  12.             Node *next;
  13.             T data;
  14.         };
  15.     public// 迭代器
  16.         class iterator
  17.         {
  18.             /
  19.         };
  20.     public:
  21.         list()
  22.         { 
  23.             theSize = 0;
  24.             head = new Node;
  25.             head->next = head->prev = head; // 指向自身的指针
  26.         }
  27.         ~list();
  28.     public:
  29.           // 成员函数
  30.     private:
  31.         Node *head; // 头指针
  32.         int theSize; // 元素个数
  33. };
  34. #endif

list类被声明为一个模板类.其节点数据结构嵌套在list种定义了.既然是双向,需要两个指针分别指向前和后,Node * prev,*next; 节点种存储的数据是类型T data;

list类有一个成员变量Node *head; 这个指针被初始化为指向自身.作为一个链表的头结点(同时它又是尾节点),这样做的好处是在插入和删除元素的时候可以省去判断很多特例.一旦这样被初始化,任何时候插入和删除都可以用一种形式逻辑完成....(自己在图纸上画画,很快会明白的......发现写stl的人就是牛叉..)

有了数据结构就应该写它的功能了..

一个链表,最基础的应该有插入,删除的功能吧.

  1. // 在itr处插入元素
  2. template <typename T>
  3. list<T>::iterator list<T>::insert(iterator itr,const T&e)
  4. {
  5.     Node *pNewNode = new Node(e,itr->prev,itr.cur);
  6.     itr->prev->next = pNewNode;
  7.     itr->prev = pNewNode;
  8.     theSize++;
  9.     return iterator(pNewNode);
  10. }
  11. // 删除itr位置处的元素
  12. template<typename T>
  13. list<T>::iterator list<T>::erase(iterator &itr)
  14. {
  15.     iterator itrTemp = iterator(itr->next);
  16.     itr->prev->next = itr->next;
  17.     itr->next->prev = itr->prev;
  18.     delete itr.cur;
  19.     theSize--;
  20.     return itrTemp;
  21. }
链表的逻辑在初学的时候容易让人迷惑,但是"顿悟"之后,发现链表的逻辑是相当简单的.

在这两个函数中,用到了iterator类型的参数.

iterator也是一个list的嵌套类型定义. 它有一个变量成员,Node *cur; 是节点类型的指针,保存当前指向的节点的地址.....有很多成员函数,都是操作符的重载.

  1.    
    1.                 class iterator
    2.         {
    3.             friend class list<T>;
    4.             public:
    5.                 iterator(){ cur=NULL; };
    6.                 Node* operator->(){ return cur;}
    7.                 T &operator*(){ return cur->data; }
    8.                 iterator operator++()
    9.                 {
    10.                     cur = cur->next;
    11.                     return cur;
    12.                 }
    13.                 iterator operator++(int)
    14.                 {
    15.                     iterator d = cur->next;
    16.                     cur = cur->next;
    17.                     return d;
    18.                 }
    19.                 bool operator==(const iterator&itr){ return itr.cur == cur; }
    20.                 bool operator!=(const iterator&itr){ return itr.cur != cur; }
    21.                 void operator=(const iterator&itr){ cur = itr.cur; }
    22.             protected:
    23.                 iterator(Node *p){ cur = p; }
    24.                 Node *cur;
    25.         };

我们要用它来遍历链表,实现插入和删除等操作

有了这些重载的操作符,对链表的操作就相当简单了.比如要取得 某个元素 *itr就ok了.要向后遍历,itr++,或者++itr.还有其他的向前遍历--itr.itr--.....itr是类对象,但是有了操作符的重载,用起来就像是一个指针一样,特爽.

对于其他的函数 push_front() push_back  begin,back的实现.有了上面的基础就相当简单了.

  1. // 将节点加入链表头部,head的后面
  2. template<typename T>
  3. void list<T>::push_front(const T&e)
  4. {
  5.     insert(begin(),e);
  6. }
  7. //将一个元素加入到链表的尾部
  8. template<typename T>
  9. void list<T>::push_back(const T&e)
  10. {
  11.     insert(end(),e);
  12. }
  13. iterator begin()const { return iterator(head->next);}  // 返回头结点指针
  14. iterator end()const { return iterator(head); } // 返回尾结点后面的指针
  15. T &front(){ return head->next->data; } // 返回第一个节点的元素
  16. T &back(){ return head->prev->data; } // 返回最后一个节点的元素

具体就不分析了...

编程群C,C++,MFC 58698324

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值