STL
- 一、自制链表容器/基本链表容器
- 1.1 首/尾部增删节点
- 1.2 获取首/尾部的元素
- 1.3 清空链表7 / 判空链表 / 链表大小8
- 1.4 缺省构造0/拷贝构造10/析构函数9
- 1.5 输出流操作符重载
- 二、迭代器原理
- 2.1 迭代器概念
- 2.2 迭代器的分类
- 三、迭代器实现
- 3.1 正向非常迭代类
- 3.2 正向非常迭代器
- 四、正向常迭代器
- 4.1 正向常迭代类
- 4.2 正向常迭代器
- 五、查找/排序功能
一、自制链表容器/基本链表容器
自制链表容器
自制一个每个节点可存储数据类型不固定的链表容器。
功能列表:
- 首/尾部增删节点
- 获取首/尾部的元素
- 清空链表 / 判空链表 / 链表大小
- 缺省构造/拷贝构造/析构函数
- 输出流操作符重载
双向链表:每个节点至少包含三个部分,前指针、中间数据、后指针。
双向链表头结点的头指针指向为空(非循环链表中指向尾节点);尾结点同样指向尾空。
只需要两个变量即可表示一个list对象,
1.1 首/尾部增删节点
- 链表为空1
bool empty(){
return m_head==NULL && m_tail==NULL;
}
- 添加链表头节点2
准备工作:红色部分代码: new Node(NULL, data, m_head);
第一步:原来的m_head指向新节点
m_head = new Node(NULL, data, m_head);
第二步:原来的第一个节点的头指针m_prev应指向新节点
m_head->next->m_prev = m_head;
void push_front(T const& data){
m_head = new node(NULL,data,m_head);
if(m_head->m_next)
m_head->m_next->m_prev = m_head;
else
m_tail = m_head;
}
- 删除链表头节点3
如上直接delete m_head
不可取,这样会导致无法找到list;
所以在删除之前应该先将第二个节点备份,再使之成为新的头结点:node* pnode = m_head; delete m_head;
再将m_head
指向备份节点并将其备份节点的头指针指向NULL
。
void pop_front(){
if(empty())
return;
node* pnode = m_head->m_next;
delete(m_head);
if(pnode)
pnode->m_prev = NULL;
else
m_tail = NULL;
m_head = pnode;
}
- 添加链表尾节点5
void push_back(T const& data){
m_tail = new node(m_tail, data, NULL);
if(m_tail->m_prev)
m_tail->m_prev->m_next = m_tail;
else
m_head = m_tail;
}
- 删除链表尾节点6
void pop_back(){
if(empty())
return;
node* pnode = m_tail->m_prev;
delete(m_tail);
if(pnode)
pnode->m_next = NULL;
else
m_head = NULL;
m_tail = pnode;
}
1.2 获取首/尾部的元素
- 获取头节点数据4
T& front(){
if(empty())
throw underflow_error("front():null node");
return m_head->m_data;
}
T const& front()const{
return const_cast<list*>(this)->front();
}
- 获取尾节点数据
T& back(){
if(empty())
throw underflow_error("back():null node");
return m_tail->m_data;
}
T const& back()const{
return const_cast<list*>(this)->back();
}
1.3 清空链表7 / 判空链表 / 链表大小8
void clear(){
while(!empty())
pop_front();
}
size_t size(){
size_t i = 0;
for(node* pnode=m_head; pnode; pnode=pnode->m_next)
i++;
return i;
}
1.4 缺省构造0/拷贝构造10/析构函数9
编译器默认提供的拷贝构造属于浅拷贝,此处应该实现深拷贝。
list():m_head(NULL),m_tail(NULL){}
//深拷贝
list(list const& that):m_head(NULL),m_tail(NULL){
for(node* pnode=that.m_head; pnode; pnode=pnode->m_next)
push_back(pnode->m_data);
}
~list(){
clear();
}
size_t size(){
size_t i = 0;
for(node* pnode=m_head; pnode; pnode=pnode->m_next)
i++;
return i;
}
1.5 输出流操作符重载
ostream& operator<<(ostream& os, list const& l){
for(node* pnode=l.m_head; pnode; pnode=pnode->m_next)
os << pnode->m_data << ' ';
return os;
}
baseList.cpp
#include <iostream>
#include <stdexcept> //提供关于异常类的声明
using namespace std;
template<class T>class list{
public:
//
//缺省构造
//
list():m_head(NULL),m_tail(NULL){}
//
//拷贝构造(可以后边实现)
//
list(list const& that):m_head(NULL),m_tail(NULL){
for(node*pnode=that.m_head; pnode; pnode=pnode->m_next){
push_back(pnode->m_data);
}
}
//
//析构函数
//
~list(){
clear();
}
//
//链表判空
//
bool empty(){
retur m_head == NULL && m_tail =+ NULL;
}
//
//添加头结点
//
void push_front(T const & data){
if(empty())
return;
node* pnode = m_head->m_next;
delete m_head;
if(pnode)
pnode->m_prev = NULL;
else
m_tail = NULL;
m_head = pnode;
}
//
//删除链表头结点
//
void pop_front(){
node* pnode = m_head;
delete m_head;
}
//
//获取头结点元素
//
T& front(){
if(empty())
throw underflow_error("null node");
return m_head->m_data;
}
//此处针对有const修饰的list
T const& front()const{
return const_cast<list*>(this)->front();
}
//
//添加尾结点
//
void push_back(T const& data){
m_tail = new node(m_tail,data,NULL);
if(m_tail->m_prev)
m_tail->m_prev->m_next = m_tail;
else
m_head = m_tail;
}
//
//删除尾结点
//
void pop_back(){
if(empty())
return;
node* pnode = m_tail->m_prev;
delete m_tail;
if(pnode)
pnode->m_next = NULL;
else
m_head = NULL;
m_tail = pnode;
}
//
//获取尾结点数据
//
T& back(){
if(empty())
throw underflow_error("null node");
return m_tail->m_data;
}
T const& back()const{
return const_cast<list*>(this)->back();
}
//
//清空链表
//
void clear(){
while(!empty()){
pop_front();
}
}
//
//获取链表大小
//
size_t size(){
size_t i=0;
for(node* pnode=m_head; pnode; pnode=pnode->m_next)
++i;
return i;
}
private:
//
//节点类
//
class node{
public:
node(node*prev,T const& data,node*next):m_prev(prev),m_data(data),m_next(next){}
//三个成员
node* m_prev;//前指针
T m_data;//节点数据
node* m_next;//后指针
};
//list只需要两个成员变量就可以表示
node* m_head;//链表头
node* m_tail;//链表尾
//声明为友元即可访问私有成员
friend ostream& operator<<(ostream& os, list<int>& l);
};
//以上代码模拟容器
//------------------------
//以下代码模拟普通用户
ostream& operator<<(ostream& os, list<int>& l){
for(list<int>::node* pnode=l.m_head; pnode; pnode=pnode->m_next){
os << pnode->m_data << ' ';
}
return os;
}
int main(){
list<int> ls;
for(int i=0; i<5; i++)
ls.push_front(10+i);
for(int i=0; i<5; i++)
ls.push_back(100+i);
cout << ls << endl;
ls.pop_front();
ls.pop_back();
cout << ls << endl;
return 0;
}
二、迭代器原理
2.1 迭代器概念
-
迭代器就是一个类(迭代类)对象。
上文所说的每一个节点即为一个迭代器对象;
迭代器三个成员皆为指针:开始指向、当前指向、终止指向分别;开始指向指向链表头结点,终止指向指向链表尾结点,当前指向可以指向开始指向和终止指向圈定范围的所有节点(包括首尾节点)
-
通过对这个对象进行操作(例如 ++/–)可以对链表容器进行某种程度(全局或局部)的遍历(又名遍历器)。
-
这样可以使用户不必关心链表容器的内部结构。
上文自制链表操作时需要对链表内部结构非常清楚,而迭代器不需要。
访问:++/–;取值:*;判断相等否:==/!=
红色为起始迭代器,蓝色为终止迭代器,区别在于蓝色的中间指向是指向链表尾结点的下一个位置(实际为NULL)。
在对红色迭代器遍历时,当红色迭代器和蓝色迭代器相等时,遍历终止。
2.2 迭代器的分类
-
正向非常迭代类 iterator
-
正向常迭代类 const_iterator
-
反向非常迭代类 reverse_iterator
-
反向常迭代类 const_reverse_iterator
三、迭代器实现
3.1 正向非常迭代类
class iterator{
public:
iterator(node*start,node*cur,node*end):
m_start(start),m_cur(cur),m_end(end){}
T& operator*() { ... }
iterator& operator++() { ... }
iterator& operator--() { ... }
bool operator==(iterator const& that)const { ... }
bool operator!=(iterator const& that)const { ... }
private:
node* m_start;
node* m_cur;
node* m_end;
};
3.2 正向非常迭代器
- 起始迭代器
iterator begin(){
return iterator(m_head,m_head,m_tail);
}
- 终止迭代器
iterator end(){
return iterator(m_head,NULL,m_tail);
}
- 迭代器指向位置添加节点
void insert(iterator const& loc, T const& data){
if(loc==end()){
push_back(data);
}else{
node* pnode = new node(loc.m_cur->m_prev, data, loc.m_cur);
if(pnode->m_prev)
pnode->m_prev->m_next = pnode;
else
m_head = pnode;
pnode->m_next->m_prev = pnode;
}
}
- 删除迭代器指向的节点
void erase(iterator const& loc){
if(loc==end())
throw underflow_error("null node");
node* pdel = loc.m_cur;
node* pnext = loc.m_cur->m_next;
if(pdel->m_prev)
pdel->m_prev->m_next = pdel->m_next;
else
m_head = pdel->m_next;
if(pdel->m_next)
pdel->m_next->m_prev = pdel->m_prev;
else
m_tail = pdel->m_prev;
delete pdel;
}
四、正向常迭代器
4.1 正向常迭代类
class const_iterator{
public:
const_iterator(iterator const& it):m_it(it){}
T const& operator*() { ... }
const_iterator& operator++() { ... }
const_iterator& operator--() { ... }
bool operator==(const_iterator const& that)const { ... }
bool operator!=(const_iterator const& that)const { ... }
private:
iterator m_it;
};
4.2 正向常迭代器
- 起始迭代器
const_iterator begin()const{
return iterator(m_head,m_head,m_tail);
}
- 终止迭代器
const_iterator end()const{
return iterator(m_head,NULL,m_tail);
}
五、查找/排序功能
- 查找功能
template<class IT,class T>IT find(IT const& begin, IT const& end, T const& data){
for(IT it=begin; it!=end; ++it){
if(*it==data)
return it;
}
return end;
}
- 利用“<”实现排序
template<class IT>IT sort(IT const& begin, IT const& end){
IT p = begin; IT last = end; --last;
for(IT i=begin, j=last; i!=j; ){
while(i!=p && *i<*p)
++i;
if(i!=p){
swap(*i,*p); p = i;
}
while(j!=p && *p<*j)
--j;
if(j!=p){
swap(*p,*j); p = j;
}
}
//递归代码;
IT it = begin;
++it;
if(p!=begin && p!=it)
sort(begin,p);
it = p;
++it;
if(it!=end && it!=last)
sort(it,end);
}
- 利用“比较器”实现排序
template<class IT,class CMP>IT sort(IT const& begin, IT const& end, CMP cmp){
IT p = begin; IT last = end; --last;
for(IT i=begin, j=last; i!=j; ){
while(i!=p && cmp(*i,*p))
++i;
if(i!=p){
swap(*i,*p); p = i;
}
while(j!=p && cmp(*p,*j))
--j;
if(j!=p){
swap(*p,*j); p = j;
}
}
//递归代码;
IT it = begin;
++it;
if(p!=begin && p!=it)
sort(begin,p,cmp);
it = p;
++it;
if(it!=end && it!=last)
sort(it,end,cmp);
}
list.cpp
#include <iostream>
#include <stdexcept>
using namespace std;
template<class T>class list{
public:
//
//缺省构造
//
list():m_head(NULL),m_tail(NULL){}
//
//拷贝构造
//
list(list const& that):m_head(NULL),m_tail(NULL){
for(node*pnode=that.m_head; pnode; pnode=pnode->m_next){
push_back(pnode->m_data);
}
}
//
//析构函数
//
~list(){
clear();
}
//
//链表判空
//
bool empty(){
return m_head==NULL && m_tail==NULL;
}
//
//添加头节点
//
void push_front(T const& data){
m_head = new node(NULL,data,m_head);
if(m_head->m_next)
m_head->m_next->m_prev = m_head;
else
m_tail = m_head;
}
//
//删除链表头节点
//
void pop_front(){
if(empty())
return;
node* pnode = m_head->m_next;
delete m_head;
if(pnode)
pnode->m_prev = NULL;
else
m_tail = NULL;
m_head = pnode;
}
//
//获取头节点元素
//
T& front(){
if(empty())
throw underflow_error("null node");
return m_head->m_data;
}
T const& front()const{
return const_cast<list*>(this)->front();
}
//
//添加尾节点
//
void push_back(T const& data){
m_tail = new node(m_tail,data,NULL);
if(m_tail->m_prev)
m_tail->m_prev->m_next = m_tail;
else
m_head = m_tail;
}
//
//删除尾节点
//
void pop_back(){
if(empty())
return;
node* pnode = m_tail->m_prev;
delete m_tail;
if(pnode)
pnode->m_next = NULL;
else
m_head = NULL;
m_tail = pnode;
}
//
//获取尾节点数据
//
T& back(){
if(empty())
throw underflow_error("null node");
return m_tail->m_data;
}
T const& back()const{
return const_cast<list*>(this)->back();
}
//
//清空链表
//
void clear(){
while(!empty()){
pop_front();
}
}
//
//获取链表大小
//
size_t size(){
size_t i=0;
for(node* pnode=m_head; pnode; pnode=pnode->m_next)
++i;
return i;
}
private:
//
//节点类
//
class node{
public:
node(node*prev,T const& data,node*next):m_prev(prev),m_data(data),m_next(next){}
node* m_prev;//前指针
T m_data;//节点数据
node* m_next;//后指针
};
public:
//
//正向非常迭代类
//
class iterator{
public:
iterator(node*start,node*cur,node*end):m_start(start),
m_cur(cur),m_end(end){}
T& operator*(){
if(m_cur==NULL)
throw underflow_error("null node");
return m_cur->m_data;
}
iterator& operator++(){
if(m_cur==NULL)
m_cur = m_start;
else
m_cur = m_cur->m_next;
return *this;
}
iterator& operator--(){
if(m_cur==NULL)
m_cur = m_end;
else
m_cur = m_cur->m_prev;
return *this;
}
bool operator==(iterator const& that)const{
return m_start==that.m_start && m_cur==that.m_cur &&
m_end==that.m_end;
}
bool operator!=(iterator const& that)const{
return !(*this==that);
}
private:
node* m_start;//开始指向
node* m_cur;//当前指向
node* m_end;//终止指向
friend class list;
};
//
//获取起始迭代器(红色)遍历链表
//
iterator begin(){
return iterator(m_head,m_head,m_tail);
}
//
//获取终止迭代器(蓝色) 结束标志
//
iterator end(){
return iterator(m_head,NULL,m_tail);
}
//
//迭代器指向的位置添加节点
//
void insert(iterator const& loc, T const& data){
if(loc==end()){
push_back(data);
}else{
node* pnode = new node(loc.m_cur->m_prev,data,loc.m_cur);
if(pnode->m_prev)
pnode->m_prev->m_next = pnode;
else
m_head = pnode;
pnode->m_next->m_prev = pnode;
}
}
//
//删除迭代器指向的节点
//
void erase(iterator const& loc){
if(loc==end())
return;
node* pdel = loc.m_cur;
if(pdel->m_prev)
pdel->m_prev->m_next = pdel->m_next;
else
m_head = pdel->m_next;
if(pdel->m_next)
pdel->m_next->m_prev = pdel->m_prev;
else
m_tail=pdel->m_prev;
delete pdel;
}
//
//正向常迭代类
//
class const_iterator{
public:
const_iterator(iterator const& it):m_it(it){}
T const& operator*(){
return *m_it;
}
const_iterator& operator++(){
++m_it;
return *this;
}
const_iterator& operator--(){
--m_it;
return *this;
}
bool operator==(const_iterator const& that)const{
return m_it==that.m_it;
}
bool operator!=(const_iterator const& that)const{
return !(*this==that);
}
private:
iterator m_it;
};
//
//获取起始常迭代器
//
const_iterator begin()const{
return iterator(m_head,m_head,m_tail);
}
//
//获取终止常迭代器
//
const_iterator end()const{
return iterator(m_head,NULL,m_tail);
}
node* m_head;//链表头
node* m_tail;//链表尾从
};
//
//比较查找(利用“==”)
//
template<class IT,class T>IT find(IT const& a,IT const& b,T const&data)
{
for(IT it=a; it!=b; ++it){
if(*it==data){
return it;
}
}
return b;
}
//
//快速排序(“<”)
//
template<class IT>void sort(IT const& begin, IT const& end){
IT p = begin;
IT last = end;
--last;
for(IT i=begin, j=last; i!=j; ){
while(i!=p && *i<*p)
++i;
if(i!=p){
swap(*i,*p);
p = i;
}
while(j!=p && *p<*j)
--j;
if(j!=p){
swap(*p,*j);
p = j;
}
}
IT it=begin;
++it;
if(p!=begin && p!=it)
sort(begin,p);
it=p;
++it;
if(it!=end && it!=last)
sort(it,end);
}
//
//快速排序(“比较器”)
//
template<class IT,class CMP>
void sort(IT const& begin, IT const& end,CMP cmp){
IT p = begin;
IT last = end;
--last;
for(IT i=begin, j=last; i!=j; ){
while(i!=p && cmp(*i,*p))//*i<*p)
++i;
if(i!=p){
swap(*i,*p);
p = i;
}
while(j!=p && cmp(*p,*j))//*p<*j)
--j;
if(j!=p){
swap(*p,*j);
p = j;
}
}
IT it=begin;
++it;
if(p!=begin && p!=it)
sort(begin,p,cmp);
it=p;
++it;
if(it!=end && it!=last)
sort(it,end,cmp);
}
//以上代码模拟容器
//------------------------
//以下代码模拟普通用户
void print(string const& str, list<int>& l){
cout << str << endl;
typedef list<int>::iterator IT;
for(IT it=l.begin(); it!=l.end(); ++it){
cout << *it << ' ';
}
cout << endl << "---------------------" << endl;
}
//
//比较类
//
class ZJW{
public:
bool operator()(int const& a, int const& b){
return a > b;
}
};
int main(){
list<int> ls;
for(int i=0; i<5; i++)
ls.push_front(10+i);
for(int i=0; i<5; i++)
ls.push_back(100+i);
print("添加节点后:", ls);
ls.pop_front();
ls.pop_back();
print("删除头尾节点后:", ls);
ls.insert(++ls.begin(),1000);//增
print("在迭代器指向的位置添加节点后:", ls);
ls.erase(ls.begin());//删
print("删除迭代器指向的节点后:", ls);
typedef list<int>::iterator IT;
IT it = ls.begin();
*it = 800;//改
print("更改迭代器指向的节点后:", ls);
IT fit = find(ls.begin(), ls.end(), 100);
if(fit!=ls.end())
ls.erase(fit);
print("找到100并删除后:", ls);
// sort(ls.begin(),ls.end());
ZJW zjw;//比较器
sort(ls.begin(),ls.end(),zjw);
print("排序后:", ls);
/*
const list<int> cls(ls);
typedef list<int>::const_iterator CIT;
for(CIT cit=cls.begin(); cit!=cls.end(); ++cit){
cout << *cit << ' ';
}
cout << endl << "------------------" << endl;
CIT cit = cls.begin();
// *cit = 900; //error*/
return 0;
}