STL(Standard template Library):c++的标准模板库

STL是算法和数据结构的软件框架,它包含了六大组件:算法、迭代器、容器、仿函数、配接器、空间配置器。

迭代器:我们可以把迭代器相当于智能指针,(其实指针也就是一个迭代器)迭代器的类型有:前向迭代器(适用于单链表),双向迭代器(适用于双向链表),随机迭代器(随机指向),反向迭代器。

容器:像vector,list,map,set这些都属于容器。分为序列式容器、关联式容器及其他容器。

序列式容器:vector、list、deque、string

关联式容器:set、map、multiset、multimap、hash_set、hash_map、hash_multiset、hash_multimap

其他容器:stack、queue、bitset

仿函数:我们之前在冒泡排序的时候用opertor()模拟实现仿函数,来实现排序的升序和降序。

配接器:是一种设计模式,它在原有类型的基础上扩展成为另一个接口,使原本因为接口不兼容而不能合作的类型可以一起工作。就类似于电源适配器一样。这里有应用于容器的适配器,应用于仿函数的适配器,应用于配接器的适配器等。

空间配置器:用户数据都是保存在内存中的,那么内存的申请释放(malloc/free)工作都是由“空间配置器”承担的。标准c++中提供了std::allocator类。

我们今天要模拟实现STL中的list:(STL库中的list是一个双向循环且带头节点的链表)

它的节点原型是这样的:

template<typename T>
struct ListNode
{
    struct ListNode* _next;             //指向下一个节点,即后继节点
    struct ListNode* _prev;             //指向前一个节点,即前驱节点
    T _data;
    ListNode(const T& data)
        :_data(data)
        ,_next(NULL)
        ,_prev(NULL)
    {}
};

我们还要用到迭代器,重载了++、--、*、->、==、!=等操作符。主要实现了以下函数:

begin:指向的是第一个元素的位置,即头节点的下一个位置;

end:指向的是最后一个元素的下一个位置,即头节点的位置。

如图:

对于迭代器,还有一个重要的问题就是迭代器失效的问题,当然迭代器失效和指针指向未知区域的道理是一样的。存在的原因是删除的时候,在链表中,你删除一个元素后,指针必须修改位置,即保存起来以便找到下一个位置。

举个例子(迭代器失效):

//list.cpp

#include<iostream>
using namespace std;
#include<list>
#include<algorithm>void Print(list<int> l)
{list<int>::iterator it = l.begin();while(it != l.end()){cout<<*it<<" ";++it;}
}int main()
{list<int> l;l.push_back(1);l.push_back(2);l.push_back(3);l.push_back(4);list<int>::iterator it = l.begin();while(it != l.end()) {if(*it == 2) {l.erase(it);      //it删除后不知道指向哪里}++it;}Print(l);return 0;
}

看一下监视窗口:

删除前:

删除后:

那么怎么解决迭代器失效问题呢?

只要保存之前it的指向,以便找到下一个指向就ok啦。

 list<int>::iterator it = l.begin();while(it != l.end()){if(*it == 2){it = l.erase(it);       //此处用it来接收解决迭代器失效问题}++it;}

运行结果:

再来说说list,对于库里边的list的函数,如push_back,pop_back,push_front,pop_front,Insert,Erase等函数,下面一 一实现一下哦。

//List.h

#pragma once
#include<iostream>
using namespace std;
template<typename T>
struct ListNode
{struct ListNode* _next;struct ListNode* _prev;T _data;ListNode(const T& data):_data(data),_next(NULL),_prev(NULL){}
};template<typename T,typename Ref,typename Ptr>
struct ListIterator
{typedef ListNode<T> Node;typedef ListIterator<T,T&,T*> Iterator;typedef ListIterator<T,const T&,const T*> ConstIterator;typedef ListIterator<T,Ref,Ptr> Self;ListIterator(Node* node):_node(node){}bool operator==(const Self& x){return _node == x._node;}bool operator!=(const Self& x){return _node != x._node;}Ref operator*(){return (*_node)._data;}Ref operator*() const{return (*_node)._data;}Ptr operator->(){return &(*_node)._data;}Self& operator++(){_node = (*_node)._next;return *this;}Self operator++(int){Self tmp = *this;++(*this);return tmp;}Self& operator--(){_node = (*_node)._prev;return *this;}Self operator--(int){Self tmp = *this;--(*this);return tmp;}Node* _node;
};template<typename T>
class List
{
public:typedef ListNode<T> Node;typedef ListIterator<T,T&,T*> Iterator;typedef ListIterator<T,const T&,const T*> ConstIterator;
public:Node* BuyNode(const T& data){return new Node(data);}
public:List():_head(BuyNode(T())){_head->_next = _head;_head->_prev = _head;}
public:Iterator Begin()              {return (*_head)._next;}Iterator End(){return _head;}ConstIterator Begin() const{return (*_head)._next;}ConstIterator End() const{return _head;}public:void PushBack(const T& data)              //尾插{Node* tmp = BuyNode(data);Node* tail = _head->_prev;tail->_next = tmp;tmp->_prev = tail;tmp->_next = _head;_head->_prev = tmp;}void PopBack()                //尾删{Node* del = _head->_prev;Node* pre = del->_prev;Node* next = del->_next;pre->_next = next;next->_prev = pre;delete del;}void PushFront(const T& data)          //头插{Node* tmp = BuyNode(data);Node* next = _head->_next;_head->_next = tmp;tmp->_prev = _head;tmp->_next = next;next->_prev = tmp;}void PopFront()               //头删{Node* prev = _head->_prev;Node* next = _head->_next;prev->_next = next;next->_prev = prev;_head = next;}Iterator Insert(Iterator pos,const T& data)      //某一个位置前插入{Node* tmp = BuyNode(data);Node* prev = pos._node->_prev;Node* cur = pos._node;prev->_next = tmp;tmp->_prev = prev;tmp->_next = cur;cur->_prev = tmp;return tmp;}ConstIterator Insert(ConstIterator pos,const T& data)      //某一个位置前插入{Node* tmp = BuyNode(data);Node* prev = pos._node->_prev;Node* cur = pos._node;prev->_next = tmp;tmp->_prev = prev;tmp->_next = cur;cur->_prev = tmp;return tmp;}Iterator Erase(Iterator pos)            //删除某个位置{assert(pos._node && pos._node != _head);    //判断节点是否为空,或只剩一个头节点Node* prev = pos._node->_prev;Node* next = pos._node->_next;prev->_next = next;next->_prev = prev;delete pos._node;return Iterator(next);           //返回下一个位置}bool Empty()        //判断链表是否为空{return _head == _head->_next;}T& Front(){return _head->_next->_data;}T& Back(){return _head->_prev->_data;}const T& Front() const{return _head->_next->_data;}const T& Back() const{return _head->_prev->_data;}void Swap(List<T>& l){swap(_head,l._head);}template<typename InputIterator>void Insert(Iterator pos,InputIterator first,InputIterator last){while(first != last){Insert(pos,*first);++first;}}void Insert(Iterator pos,ConstIterator first,ConstIterator last)  //在pos位置插入一段区间{for(;first != last;++first)Insert(pos,*first);}
private:Node* _head;
};void PrintList(List<int>& l)
{List<int>::Iterator it = l.Begin();while(it != l.End()){cout<<*it<<" ";++it;}cout<<endl;
}

//List.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"
#include<vector>
int main()
{List<int> l;List<int> l1;const List<int> l3;l.PushBack(1);l.PushBack(2);l.PushBack(3);l.PushBack(4);l.PopBack();PrintList(l);l.PushFront(0);PrintList(l);l.PopFront();l.Insert(l.End(),4);l.Insert(l.Begin(),0);PrintList(l);cout<<"Front:"<<l.Front()<<endl;cout<<"Back:"<<l.Back()<<endl;cout<<"Empty:"<<l.Empty()<<endl;l1.Swap(l);PrintList(l1);PrintList(l);l.PushBack(10);l.PushBack(11);l.PushBack(12);l1.Insert(l1.Begin(),l.Begin(),l.End());PrintList(l1);vector<int> v;v.push_back(55);v.push_back(66);l1.Insert(l1.Begin(),v.begin(),v.end());PrintList(l1);char str[] = {'a','b'};l1.Insert(l1.Begin(),str,str+2);PrintList(l1);return 0;
}

运行结果:

[STL]List的实现相关推荐

  1. STL库(C++11)提供的异步执行方法的方式

    在进行并发编程的时候难免会遇到异步执行时候,现代C++标准库提供了几种异步执行的方式,本文收集整理了一下,以备将来翻阅. Thread方式 Thread 是STL提供的一种快捷创建线程的方式,极大方便 ...

  2. C++ 笔记(24)— STL map 类(map实例化、插入、查找、删除)

    1. STL 映射类简介 map 和 multimap 是键-值对容器,支持根据键进行查找,区别在于,后者能够存储重复的键,而前者只能存储唯一的键. 为了实现快速查找, STL map 和 multi ...

  3. C++ 笔记(23)— STL vector 类(实例化 vector、末尾插入、指定位置插入、数组方式访问元素、指针方式访问元素、删除元素、大小与容量区别)

    1. vector 特点 vector 是一个模板类,提供了动态数组的通用功能,具有如下特点: 在数组末尾添加元素所需的时间是固定的,即在末尾插入元素的所需时间不随数组大小而异,在末尾删除元素也如此: ...

  4. C++ 笔记(22)— STL string 类(字符串赋值、访问、拼接、查找、翻转、大小写转换)

    1. 实例化和赋值 STL string #include <string> #include <iostream>int main () {using namespace s ...

  5. C++ 笔记(19)— 标准模板库(STL容器、STL迭代器、STL算法、STL容器特点、STL字符串类)

    C++ 标准库可以分为两部分: 标准函数库: 这个库是由通用的.独立的.不属于任何类的函数组成的.函数库继承自 C 语言. 面向对象类库: 这个库是类及其相关函数的集合. C++ 标准库包含了所有的 ...

  6. STL map 简介

    STL map 简介 转载于:http://www.cnblogs.com/TianFang/archive/2006/12/30/607859.html 1.目录 map简介 map的功能 使用ma ...

  7. 【STL源码剖析读书笔记】【第5章】关联式容器之hashtable

    1.hashtable在插入.删除.搜寻操作上具有"常数平均时间"的表现,不依赖输入元素的随机性. 2.hashtable通过hashfunction将元素映射到不同的位置,但当不 ...

  8. C++ stl vector介绍

    转自: STL vector用法介绍 介绍 这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作.本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if ...

  9. STL vector list deque区别与实现

    1 vector 向量 相当于一个数组     在内存中分配一块连续的内存空间进行存储.支持不指定vector大小的存储.STL内部实现时,首先分配一个非常大的内存空间预备进行存储,即capacitu ...

  10. 用法 stl_51Nod 2160 数字游戏 STL基本用法

    目录 目录 1. 题目描述 1.1. Limit 1.2. Problem Description 1.3. Input 1.4. Output 1.5. Sample Input 1.6. Samp ...

最新文章

  1. php扩展xdebug基本使用
  2. R语言数据结构之数组
  3. java创建对象的5种方法
  4. linux shell 字符串比较相等、不相等
  5. 软件著作权登记证书申请攻略
  6. Java笔记:与系统交互、系统相关的类,Object类
  7. 一篇故事讲述了计算机网络里的基本概念:网关,DHCP,IP寻址,ARP欺骗,路由,DDOS等...
  8. MyBatis : Example 条件查询 in 用法
  9. Windows Server AppFabric Caching支持大数据量的配置
  10. String str 与 String str=new String() 区别
  11. 交通运输部·车载导航系统——终端如何与服务器通信——玩转通信协议(源码下载)...
  12. 域控查看ldap端口命令_LDAP基础安装与简单入门使用
  13. android系统硬件OpenGL 3D移植(二)
  14. Unity web player无法正常使用
  15. java 对象转换成map_Java中对象(Object)转换成Map
  16. 手机如何无线投屏到电视/电脑
  17. 8卡gpu服务器是8个芯片,GPU服务器 4GPU 8GPU 运算卡
  18. 2013, Samara SAU ACM ICPC Quarterfinal Qualification Contest C.Victor‘s Research
  19. 云计算技术的应用和前景
  20. 新的天花?高通量如何加速抗猴痘病毒化合物筛选 | MedChemExpress

热门文章

  1. Iterator作用
  2. Hive中的数据库、表、数据与HDFS的对应关系
  3. 如何在自己的代码中实现分享视频文件或者是图片文件到微信 QQ微博 新浪微博等!!!...
  4. vi @-function
  5. DM9000调试记录
  6. 【css】CSS中折叠margin的问题
  7. 2012服务器系统关闭网络共享,提供网络服务的前提,Windows Server 2012如何更改高级共享设置...
  8. 循环数组对象 php,PHP循环遍历stdClass对象的数组
  9. druid连接池初始化慢_7、SpringBoot -连接池(Durid)
  10. html浮动炫酷样式,jQuery和CSS3炫酷表单浮动标签特效