[STL]List的实现
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的实现相关推荐
- STL库(C++11)提供的异步执行方法的方式
在进行并发编程的时候难免会遇到异步执行时候,现代C++标准库提供了几种异步执行的方式,本文收集整理了一下,以备将来翻阅. Thread方式 Thread 是STL提供的一种快捷创建线程的方式,极大方便 ...
- C++ 笔记(24)— STL map 类(map实例化、插入、查找、删除)
1. STL 映射类简介 map 和 multimap 是键-值对容器,支持根据键进行查找,区别在于,后者能够存储重复的键,而前者只能存储唯一的键. 为了实现快速查找, STL map 和 multi ...
- C++ 笔记(23)— STL vector 类(实例化 vector、末尾插入、指定位置插入、数组方式访问元素、指针方式访问元素、删除元素、大小与容量区别)
1. vector 特点 vector 是一个模板类,提供了动态数组的通用功能,具有如下特点: 在数组末尾添加元素所需的时间是固定的,即在末尾插入元素的所需时间不随数组大小而异,在末尾删除元素也如此: ...
- C++ 笔记(22)— STL string 类(字符串赋值、访问、拼接、查找、翻转、大小写转换)
1. 实例化和赋值 STL string #include <string> #include <iostream>int main () {using namespace s ...
- C++ 笔记(19)— 标准模板库(STL容器、STL迭代器、STL算法、STL容器特点、STL字符串类)
C++ 标准库可以分为两部分: 标准函数库: 这个库是由通用的.独立的.不属于任何类的函数组成的.函数库继承自 C 语言. 面向对象类库: 这个库是类及其相关函数的集合. C++ 标准库包含了所有的 ...
- STL map 简介
STL map 简介 转载于:http://www.cnblogs.com/TianFang/archive/2006/12/30/607859.html 1.目录 map简介 map的功能 使用ma ...
- 【STL源码剖析读书笔记】【第5章】关联式容器之hashtable
1.hashtable在插入.删除.搜寻操作上具有"常数平均时间"的表现,不依赖输入元素的随机性. 2.hashtable通过hashfunction将元素映射到不同的位置,但当不 ...
- C++ stl vector介绍
转自: STL vector用法介绍 介绍 这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作.本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if ...
- STL vector list deque区别与实现
1 vector 向量 相当于一个数组 在内存中分配一块连续的内存空间进行存储.支持不指定vector大小的存储.STL内部实现时,首先分配一个非常大的内存空间预备进行存储,即capacitu ...
- 用法 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 ...
最新文章
- php扩展xdebug基本使用
- R语言数据结构之数组
- java创建对象的5种方法
- linux shell 字符串比较相等、不相等
- 软件著作权登记证书申请攻略
- Java笔记:与系统交互、系统相关的类,Object类
- 一篇故事讲述了计算机网络里的基本概念:网关,DHCP,IP寻址,ARP欺骗,路由,DDOS等...
- MyBatis : Example 条件查询 in 用法
- Windows Server AppFabric Caching支持大数据量的配置
- String str 与 String str=new String() 区别
- 交通运输部·车载导航系统——终端如何与服务器通信——玩转通信协议(源码下载)...
- 域控查看ldap端口命令_LDAP基础安装与简单入门使用
- android系统硬件OpenGL 3D移植(二)
- Unity web player无法正常使用
- java 对象转换成map_Java中对象(Object)转换成Map
- 手机如何无线投屏到电视/电脑
- 8卡gpu服务器是8个芯片,GPU服务器 4GPU 8GPU 运算卡
- 2013, Samara SAU ACM ICPC Quarterfinal Qualification Contest C.Victor‘s Research
- 云计算技术的应用和前景
- 新的天花?高通量如何加速抗猴痘病毒化合物筛选 | MedChemExpress
热门文章
- Iterator作用
- Hive中的数据库、表、数据与HDFS的对应关系
- 如何在自己的代码中实现分享视频文件或者是图片文件到微信 QQ微博 新浪微博等!!!...
- vi @-function
- DM9000调试记录
- 【css】CSS中折叠margin的问题
- 2012服务器系统关闭网络共享,提供网络服务的前提,Windows Server 2012如何更改高级共享设置...
- 循环数组对象 php,PHP循环遍历stdClass对象的数组
- druid连接池初始化慢_7、SpringBoot -连接池(Durid)
- html浮动炫酷样式,jQuery和CSS3炫酷表单浮动标签特效