p15~p22基本链表容器和高级链表容器迭代器

一、自制链表容器/基本链表容器

自制链表容器

自制一个每个节点可存储数据类型不固定的链表容器。

功能列表:

  • 首/尾部增删节点
  • 获取首/尾部的元素
  • 清空链表 / 判空链表 / 链表大小
  • 缺省构造/拷贝构造/析构函数
  • 输出流操作符重载

双向链表:每个节点至少包含三个部分,前指针、中间数据、后指针。

在这里插入图片描述

在这里插入图片描述

双向链表头结点的头指针指向为空(非循环链表中指向尾节点);尾结点同样指向尾空。

在这里插入图片描述
只需要两个变量即可表示一个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 ITclass 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我宿孤栈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值