(C++ STL)list的实现
#include <iostream>
using namespace std;
//採用迭代器和空间配置器所实现的双向链表的基本功能
template<class _Ty,class _A = allocator<_Ty> >
//定义模板类
class list
//list类
{
public:
typedef size_t size_type;
//类型重定义
protected:
struct _Node;
//结构体_Node
friend struct _Node;
//友元
typedef _Node* _Nodeptr;
//类型重定义
struct _Node
//结构体定义
{
_Nodeptr _Next,_Prev;
_Ty _Value;
};
protected:
_A allocator;
_Nodeptr _Head;
size_type _Size;
public:
typedef list<_Ty,_A> _Myt;
typedef _A allocator_type;
//该类型是模板參数A的同义词
typedef size_t size_type;
//正整数类型
typedef ptrdiff_t difference_type;
//整数类型
typedef _Ty* pointer;
//指向_Ty的指针
typedef const _Ty* const_pointer;
//指向_Ty的常量指针
typedef _Ty& reference;
//_Ty的引用
typedef const _Ty& const_reference;
//_Ty的常量引用
typedef _Ty value_type;
//对象类型_Ty
class iterator;
//訪问list的迭代器
class const_iterator;
//訪问list的常量迭代器
friend class const_iterator;
//友元
class const_iterator : public _Bidit<_Ty, difference_type>
//继承
{
public:
//共同拥有成员
_Nodeptr _Mynode() const
//指向当前结点
{
return (_Ptr);
}
const_iterator()
//默认构造函数
{}
const_iterator(_Nodeptr _P):_Ptr(_P)
//參数为指针的构造函数
{}
const_iterator(const iterator& _X):_Ptr(_X._Ptr)
//參数为訪问list的常量迭代器的构造函数
{}
const_reference operator*() const
//获取当前_Ty的常量的值
{
return _Ptr->_Value;
}
const_pointer operator->() const
//?
{
return (&**this);
}
const_iterator& operator++()
//前置++的引用
{
_Ptr = _Ptr->_Next;
return (*this);
}
const_iterator operator++(int)
//后置++的引用
{
const_iterator _Tmp = *this;
++*this;
return (_Tmp);
}
const_iterator& operator--()
//前置--的引用
{
_Ptr = _Ptr->_Prev;
return (*this);
}
const_iterator operator--(int)
//后置--的引用
{
const_iterator _Tmp = *this;
--*this;
return (_Tmp);
}
bool operator==(const const_iterator& _X) const
//推断是否相等
{
return (_Ptr == _X._Ptr);
}
bool operator!=(const const_iterator& _X) const
//推断是否不等
{
return (!(*this == _X));
}
protected:
//保护成员
_Nodeptr _Ptr;
};
friend class iterator;
//友元
class iterator : public const_iterator
//继承
{
public:
iterator()
//默认构造函数
{}
iterator(_Nodeptr _P): const_iterator(_P)
//參数为指针的构造函数
{}
reference operator*() const
//获取当前_Ty的值
{
return _Ptr->_Value;
}
_Ty* operator->() const
//?
{
return (&**this);
}
iterator& operator++()
//前置++的引用
{
_Ptr = _Ptr->_Next;
return (*this);
}
iterator operator++(int)
//后置++的引用
{
iterator _Tmp = *this;
++*this;
return (_Tmp);
}
iterator& operator--()
//前置--的引用
{
_Ptr = _Ptr->_Prev;
return (*this);
}
iterator operator--(int)
//后置--的引用
{
iterator _Tmp = *this;
--*this;
return (_Tmp);
}
bool operator==(const iterator& _X) const
//推断是否相等
{
return (_Ptr == _X._Ptr);
}
bool operator!=(const iterator& _X) const
//推断是否不等
{
return (!(*this == _X));
}
};
public:
_Nodeptr _Buynode(_Nodeptr _Narg = 0, _Nodeptr _Parg = 0)
//购买结点
{
_Nodeptr _S = (_Nodeptr)allocator._Charalloc( //开辟空间
1 * sizeof (_Node));
_S->_Next = _Narg != 0 ? _Narg : _S;;
_S->_Prev = _Parg != 0 ? _Parg : _S;
return (_S);
}
void _Freenode(_Nodeptr _S)
//释放空间
{
allocator.deallocate(_S, 1);
}
void _Splice(iterator _P, _Myt& _X, iterator _F, iterator _L)
//拼接
{
if (allocator == _X.allocator) //将两个拼接到一起,_X清空
{
(_L._Mynode())->_Prev->_Next = _P._Mynode();
(_F._Mynode())->_Prev->_Next = _L._Mynode();
(_P._Mynode())->_Prev->_Next = _F._Mynode();
_Nodeptr _S = (_P._Mynode())->_Prev;
(_P._Mynode())->_Prev =(_L._Mynode())->_Prev;
(_L._Mynode())->_Prev =(_F._Mynode())->_Prev;
(_F._Mynode())->_Prev = _S;
}
else //将_X中的链表数值加入到_P中,_X清空
{
insert(_P, _F, _L);
_X.erase(_F, _L);
}
}
void _Xran() const
//抛出异常
{
_THROW(out_of_range, "invalid list<T> subscript");
}
public:
size_type size() const
//长度
{
return (_Size);
}
bool empty() const
//判空
{
return (size() == 0);
}
_A get_allocator() const
//返回空间配置器
{
return (allocator);
}
void resize(size_type _N, _Ty _X = _Ty())
//又一次定义链表长度
{
if (size() < _N)
{
insert(end(), _N - size(), _X);
}
else
{
while (_N < size())
{
pop_back();
}
}
}
size_type max_size() const
//返回链表最大可能长度
{
return (allocator.max_size());
}
reference front()
//返回第一个元素的引用
{
return (*begin());
}
const_reference front() const
//返回第一个元素的常量引用
{
return (*begin());
}
reference back()
//返回最后一元素的引用
{
return (*(--end()));
}
const_reference back() const
//返回最后一元素的常量引用
{
return (*(--end()));
}
_Myt& operator=(const _Myt& _X)
//运算符构造函数
{
if (this != &_X)
{
iterator _F1 = begin();
iterator _L1 = end();
const_iterator _F2 = _X.begin();
const_iterator _L2 = _X.end();
for (; _F1 != _L1 && _F2 != _L2; ++_F1, ++_F2)
{
*_F1 = *_F2;
}
erase(_F1, _L1);
insert(_L1, _F2, _L2);
}
return (*this);
}
public:
explicit list():_Head(_Buynode()), _Size(0)
//空链表
{}
explicit list(const _Ty& _V):_Head(_Buynode()), _Size(0)
//建一个含_V个默认值是0的元素的链表
{
insert(begin(),_V,0);
}
explicit list(size_type _N, const _Ty& _V):_Head(_Buynode()), _Size(0)
//建一个含_V个元素的链表。值都是_N
{
insert(begin(),_N, _V);
}
list(const _Myt& _X): _Head(_Buynode()), _Size(0)
//建一个_X的copy链表
{
insert(begin(), _X.begin(), _X.end());
}
list(const _Ty *_F, const _Ty *_L): _Head(_Buynode()), _Size(0)
//一个区域的元素[_First, _Last)。
{
insert(begin(), _F, _L);
}
typedef const_iterator _It;
list(_It _F, _It _L):_Head(_Buynode()), _Size(0)
//常量迭代器
{
insert(begin(), _F, _L);
}
iterator begin()
//迭代器第一个节点
{
return iterator(_Head->_Next);
}
const_iterator begin() const
//常量迭代器第一个节点
{
return (const_iterator(_Head->_Next));
}
iterator end()
//返回最后一个元素的下一位置的指针
{
return iterator(_Head);
}
const_iterator end() const
//返回最后一个元素的下一位置的指针
{
return (const_iterator(_Head));
}
iterator insert(iterator _P,const _Ty& _X)
//在_P之前插入结点
{
_Nodeptr _S = _P._Mynode();
_S->_Prev = _Buynode(_S,_S->_Prev);
_S = _S->_Prev;
_S->_Prev->_Next = _S;
_S->_Value = _X;
++_Size;
return (iterator(_S));
}
void insert(iterator _P,size_type _M, const _Ty& _X)
//在_P之前插入_M个_X结点
{
for(;0 < _M;--_M)
{
insert(_P,_X);
}
}
void insert(iterator _P, const _Ty *_F, const _Ty *_L)
//在_P之前插入_F到_L的结点
{
for (; _F != _L; ++_F)
{
insert(_P, *_F);
}
}
typedef const_iterator _It;
void insert(iterator _P, _It _F, _It _L)
//在_P之前插入迭代器_F到_L的结点
{
for (; _F != _L; ++_F)
{
insert(_P, *_F);
}
}
void push_front(const _Ty& _X)
//添加一元素到链表头
{
insert(begin(), _X);
}
void pop_front()
//删除链表头的一元素
{
erase(begin());
}
void push_back(const _Ty& _X)
//添加一元素到链表尾
{
insert(end(), _X);
}
void pop_back()
//删除链表尾的一个元素
{
erase(--end());
}
void assign(size_type _N, const _Ty& _X)
//分配值
{
erase(begin(),end());
insert(begin(),_N, _X);
}
iterator erase(iterator _P)
//删除_P元素
{
_Nodeptr _S = (_P++)._Mynode();
_S->_Prev->_Next = _S->_Next;
_S->_Next->_Prev = _S->_Prev;
_Freenode(_S);
--_Size;
return (_P);
}
iterator erase(iterator _F, iterator _L)
//删除_F到_L区域的元素
{
while (_F != _L)
{
erase(_F++);
}
return (_F);
}
void clear()
//删除全部元素
{
erase(begin(),end());
}
void show()
//STL源代码中不存在的函数,自己加的,为了使得測试更方便
{
_Nodeptr _P = _Head->_Next;
while(_P != _Head)
{
cout<<_P->_Value<<"-->";
_P = _P->_Next;
}
cout<<"Over"<<endl;
}
~list()
//析构函数
{
erase(begin(),end());
_Freenode(_Head);
_Head = 0, _Size = 0;
}
public:
void swap(_Myt& _X)
//交换两个链表
{
if (allocator == _X.allocator)
//若空间配置器同样,则仅仅需交换头结点和大小
{
std::swap(_Head, _X._Head);
std::swap(_Size, _X._Size);
}
else
//否则将链表分别拼接到对方空间中
{
iterator _P = begin();
splice(_P, _X);
_X.splice(_X.begin(), *this, _P, end());
}
}
friend void swap(_Myt& _X, _Myt& _Y)
//交换两个链表
{
_X.swap(_Y);
}
void splice(iterator _P, _Myt& _X)
//对两个链表进行拼接
{
if (!_X.empty())
{
_Splice(_P, _X, _X.begin(), _X.end());
_Size += _X._Size;
_X._Size = 0;
}
}
void splice(iterator _P, _Myt& _X, iterator _F)
//对两个链表进行拼接
{
iterator _L = _F;
if (_P != _F && _P != ++_L)
{
_Splice(_P, _X, _F, _L);
++_Size;
--_X._Size;
}
}
void splice(iterator _P, _Myt& _X, iterator _F, iterator _L)
//对两个链表进行拼接
{
if (_F != _L)
{
if (&_X != this)
{
difference_type _N = 0;
_Distance(_F, _L, _N);
_Size += _N;
_X._Size -= _N;
}
_Splice(_P, _X, _F, _L);
}
}
void remove(const _Ty& _V)
//从链表中删除全部值为_V的元素
{
iterator _L = end();
for (iterator _F = begin(); _F != _L; )
{
if (*_F == _V)
{
erase(_F++);
}
else
{
++_F;
}
}
}
void unique()
//删除全部反复的元素,以建立一个具有唯一元素值的链表,
//即链表中不会有反复元素
{
iterator _F = begin(), _L = end();
if (_F != _L)
{
for (iterator _M = _F; ++_M != _L; _M = _F)
{
if (*_F == *_M)
{
erase(_M);
}
else
{
_F = _M;
}
}
}
}
void merge(_Myt& _X)
//把当前链表*this和x合并,合并后x为空。
//把x中的元素插入到当前链表中。不同意两个链表同样
{
if (&_X != this)
{
iterator _F1 = begin(), _L1 = end();
iterator _F2 = _X.begin(), _L2 = _X.end();
while (_F1 != _L1 && _F2 != _L2)
{
if (*_F2 < *_F1)
{
iterator _Mid2 = _F2;
_Splice(_F1, _X, _F2, ++_Mid2);
_F2 = _Mid2;
}
else
{
++_F1;
}
}
if (_F2 != _L2)
{
_Splice(_L1, _X, _F2, _L2);
}
_Size += _X._Size;
_X._Size = 0;
}
}
void reverse()
//反转链表中的元素排序
{
if (2 <= size())
{
iterator _L = end();
for (iterator _F = ++begin(); _F != _L; )
{
iterator _M = _F;
_Splice(begin(), *this, _M, ++_F);
}
}
}
void sort()
//依据默认条件对链表进行排序?
{
if (2 <= size())
{
const size_t _MAXN = 15;
_Myt _X, _A[_MAXN + 1];
size_t _N = 0;
while (!empty())
{
_X.splice(_X.begin(), *this, begin());
size_t _I;
for (_I = 0; _I < _N && !_A[_I].empty(); ++_I)
{
_A[_I].merge(_X);
_A[_I].swap(_X);
}
if (_I == _MAXN)
{
_A[_I].merge(_X);
}
else
{
_A[_I].swap(_X);
if (_I == _N)
{
++_N;
}
}
}
while (0 < _N)
{
merge(_A[--_N]);
}
}
}
};
template<class _Ty, class _A> inline
//模板类推断是否相等
bool operator==(const list<_Ty, _A>& _X,
const list<_Ty, _A>& _Y)
{
return (_X.size() == _Y.size()
&& equal(_X.begin(), _X.end(), _Y.begin()));
}
template<class _Ty, class _A> inline
//模板类推断是否不等
bool operator!=(const list<_Ty, _A>& _X,
const list<_Ty, _A>& _Y)
{
return (!(_X == _Y));
}
template<class _Ty, class _A> inline
//模板类比較链表的大小
bool operator<(const list<_Ty, _A>& _X,
const list<_Ty, _A>& _Y)
{
return (lexicographical_compare(_X.begin(), _X.end(),
_Y.begin(), _Y.end()));
}
template<class _Ty, class _A> inline
//模板类比較链表的大小_Y < _X
bool operator>(const list<_Ty, _A>& _X,
const list<_Ty, _A>& _Y)
{
return (_Y < _X);
}
template<class _Ty, class _A> inline
//模板类比較链表的大小!(_Y < _X)
bool operator<=(const list<_Ty, _A>& _X,
const list<_Ty, _A>& _Y)
{
return (!(_Y < _X));
}
template<class _Ty, class _A> inline
//模板类比較链表的大小!(_X < _Y)
bool operator>=(const list<_Ty, _A>& _X,
const list<_Ty, _A>& _Y)
{
return (!(_X < _Y));
} void main()
{
list<int> c0; //空链表
list<int> c1(3); //建一个含三个默认值是0的元素的链表
list<int> c2(c1); //建一个c1的copy链表
list<int> c3(c1.begin(),c1.end()); //含c1一个区域的元素[_First, _Last)。
int ar[5] = {2,3,4,5,6};
list<int> itlist(ar,ar+5); //用数组赋值
list<int> mylist(3,2); //建一个含三个元素的链表,值都是2
mylist.show(); list<int> youlist(3,3);
youlist.show(); swap(mylist, youlist); //交换两个链表
mylist.show();
youlist.show(); mylist.swap(youlist);
mylist.show();
youlist.show(); list<int>::iterator i1 = itlist.begin();
itlist.splice(i1,mylist); //对两个链表进行结合
itlist.show(); itlist.remove(3);
itlist.show(); itlist.unique();
itlist.show(); itlist.merge(mylist);
itlist.show();
mylist.show(); itlist.reverse();
itlist.show(); itlist.sort();
itlist.show(); cout<<operator<(itlist,mylist)<<endl;
cout<<operator>(itlist,mylist)<<endl;
}
(C++ STL)list的实现的更多相关文章
- 详细解说 STL 排序(Sort)
0 前言: STL,为什么你必须掌握 对于程序员来说,数据结构是必修的一门课.从查找到排序,从链表到二叉树,几乎所有的算法和原理都需要理解,理解不了也要死记硬背下来.幸运的是这些理论都已经比较成熟,算 ...
- STL标准模板库(简介)
标准模板库(STL,Standard Template Library)是C++标准库的重要组成部分,包含了诸多在计算机科学领域里所常见的基本数据结构和基本算法,为广大C++程序员提供了一个可扩展的应 ...
- STL的std::find和std::find_if
std::find是用来查找容器元素算法,但是它只能查找容器元素为基本数据类型,如果想要查找类类型,应该使用find_if. 小例子: #include "stdafx.h" #i ...
- STL: unordered_map 自定义键值使用
使用Windows下 RECT 类型做unordered_map 键值 1. Hash 函数 计算自定义类型的hash值. struct hash_RECT { size_t operator()(c ...
- C++ STL简述
前言 最近要找工作,免不得要有一番笔试,今年好像突然就都流行在线笔试了,真是搞的我一塌糊涂.有的公司呢,不支持Python,Java我也不会,C有些数据结构又有些复杂,所以是时候把STL再看一遍了-不 ...
- codevs 1285 二叉查找树STL基本用法
C++STL库的set就是一个二叉查找树,并且支持结构体. 在写结构体式的二叉查找树时,需要在结构体里面定义操作符 < ,因为需要比较. set经常会用到迭代器,这里说明一下迭代器:可以类似的把 ...
- STL bind1st bind2nd详解
STL bind1st bind2nd详解 先不要被吓到,其实这两个配接器很简单.首先,他们都在头文件<functional>中定义.其次,bind就是绑定的意思,而1st就代表fir ...
- STL sort 函数实现详解
作者:fengcc 原创作品 转载请注明出处 前几天阿里电话一面,被问到STL中sort函数的实现.以前没有仔细探究过,听人说是快速排序,于是回答说用快速排序实现的,但听电话另一端面试官的声音,感觉不 ...
- STL的使用
Vector:不定长数组 Vector是C++里的不定长数组,相比传统数组vector主要更灵活,便于节省空间,邻接表的实现等.而且它在STL中时间效率也很高效:几乎与数组不相上下. #include ...
- [C/C++] C/C++延伸学习系列之STL及Boost库概述
想要彻底搞懂C++是很难的,或许是不太现实的.但是不积硅步,无以至千里,所以抽时间来坚持学习一点,总结一点,多多锻炼几次,相信总有一天我们会变得"了解"C++. 1. C++标准库 ...
随机推荐
- 【php】子类覆盖超类方法,在超类里调用此方法会出现何种现象
<?php class A { public function getName() { echo $this->name(); } function name () { return 'l ...
- php框架的特性总结
今天面试问到了php框架的特性,特此在这汇总一下,方便以后查看. Thinkphp 3.2特性: 1.多表查询非常方便,在model 里几句代码就可以完成完成多表的关联操作. 2.融合了smarty ...
- Day13有参装饰器,三元表达式,匿名函数
多个装饰器: 加载顺序:由下而上 执行顺序:由上而下 有参装饰器: 闭包,给函数传参的一种方法 当装饰器内需要参数时,可以采用闭包形式给其传参,第三层函数接收完参数时,就变为无参装饰器 三元表达式: ...
- 基础训练 2n皇后问题
2n皇后问题 #include<iostream> #include<vector> using namespace std; int cnt = 0, n; vector&l ...
- 组队赛Day1第一场 GYM 101350 F. Monkeying Around(线段树)
[题目大意] 有n只猴子坐在树上,m个笑话. 给出每个讲这个笑话的猴子的编号,笑话的编号,和笑话的影响半径. 如果一个树上的猴子听了没听过的笑话,会掉到树下.如果听过并且在树下,就会爬到树上. 问最后 ...
- cf898d Alarm Clock
区间上有 \(n\) 个点,问你为达到目的:长度为 \(m\) 的区间内点的个数都 $ < k$需要去掉多少个点. 贪心.每个区间我们总是去掉最后的,也就是说除非万不得已我们是不会去掉点的. 队 ...
- 自己项目使用了ARC,项目中使用第三方库继续引用ARC
Objective-C引入ARC(Automatic Reference Counting)后,我们经常会面对这样一种困境:自己的项目使用了ARC,却发现要使用的第三方类库是non-ARC的:又或者自 ...
- [adb 连接不上的原因] 汇总
http://www.cnblogs.com/dazhao/p/6534128.html 查看android studio 的sdk路径( 点击工具栏 ?号旁边的类似下载按钮) SDK_Manager ...
- json的两种表示结构(对象和数组).。
JSON有两种表示结构,对象和数组.对象结构以”{”大括号开始,以”}”大括号结束.中间部分由0或多个以”,”分隔的”key(关键字)/value(值)”对构成,关键字和值之间以”:”分隔,语法结构如 ...
- 九度oj 题目1254:N皇后问题
题目描述: N皇后问题,即在N*N的方格棋盘内放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在同一斜线上.因为皇后可以直走,横走和斜走如下图). 你的任务是,对 ...