迭代器iterator

源码:

```baidu
迭代器(iterator)有时又称光标(cursor)是程序设计的软件设计模式,可在容器对象(container,例如链表或数组)上遍访的接口,设计人员无需关心容器对象的内存分配的实现细节。
软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
```

效果:

迭代器(iterator)有时又称光标(cursor)是程序设计的软件设计模式,可在容器对象(container,例如链表或数组)上遍访的接口,设计人员无需关心容器对象的内存分配的实现细节。
软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。

(这波抄袭复制百度掩饰得不错)

概念

所以说,迭代器没什么高大上的,就只是一种代码经验,代码习惯。
比如说有些人习惯用\(dp_0\)表示不定长数组\(dp\)当前的长度,这就是一种代码的经验。
有人喜欢把一个程序的所有初始化(清零,读入)都放在inline void init()里面,这也是一种经验。
还有很多很多。。。
总之,迭代器只是一种程序设计的思路,可有可无。

优势

那有什么用呢?主要就让你很好的遍历容器里面的所有元素。
比如说,我定义一个队列,不给用STL(我也不知道为什么),那么你就会

int que[N],hd,ed;

然后用循环队列的方式来实现这个队列
那么如果我要按顺序访问队列中的元素
你就会

for(int i=hd;i<ed+(N&((ed-hd)>>32));i=(i+1)%N)
{
  cout<<que[i];
}

emmm...确实还可以
我定义(别问我为什么要定义)元素\(i\)\(val\)值为\(val_i\)
我要输出队列中第\(i\)个元素的\(val\)
是不是就会有人写成

cout<<val[i];

实际上应该是

cout<<val[que[i]];

如果套更多的话。。。不堪设想。
但是迭代器就没有这个问题。
迭代器实质上是一个结构体,你如果往数组下标传入结构体会类型错误,那么你就知道你调用错了。
那么你就说,这种东西细心一点也没什么嘛。。。
那好吧我承认目前我认知到迭代器最后一个功能就是
装X
反正。。。迭代器就是一种编程习惯,你爱写不写。
书写迭代器可以让你的代码更加整洁,思路更加清晰,不会让你的代码跑得更快(甚至会慢一点。。。)(敲黑板划重点)
迭代器可以保证你遍历元素的时候按照一定的顺序(比如集合set按照默认升序,链表list按照从前到后),然后调用的时候不需要关注具体的内存地址。
比如你实现平衡树的时候,如果你不写迭代器,你要求一个数的前驱或者后继,你就要一个个结点去跳前驱后继。但是如果有迭代器,直接

Treap::iterator it;
++it;

是不是很快。。。
(完了我编不下去了)

实现

这个东西其实很简单。我们用队列来举个例子。
首先你要用指针表示链表

struct que
{
  que *nxt;
  int dat;
};

然后再用一个大的结构体包装一下(也没见你调用队列之类的东西用指针调用的吧?)

struct Que
{
  struct que
  {
    que *nxt,*pre;
    int dat;
    que() { pre=nxt=0x0; dat=0; }
  }*hd,*ed; // 队头和队尾的指针
  Que() { ed=hd=new que; }
  struct iterator
  {
    que* M_current; // 当前迭代器指向的元素的指针
    iterator() { M_current=0x0; }
    iterator(que* a) { M_current=a; }
    iterator operator ++ () { M_current=M_current->nxt; return *this; } // 让迭代器指向前一个元素
    iterator operator -- () { M_current=M_current->pre; return *this; } // 让迭代器指向后一个元素
    bool operator != (iterator b) const { return M_current!=b.M_current; } // 两个迭代器不相等
    bool operator == (iterator b) const { return M_current==b.M_current; } // 两个迭代器相等,当且仅当他们指向的地址相等
    int operator * () const { return M_current->dat; } // 返回指向的元素
  };
  inline iterator begin() const { return iterator(hd); }
  inline iterator end() const { return iterator(ed); }
};

如果不是队列而是其他的话,就自增和自减运算符的实现方法不一样而已。
所以看见了吧?迭代器其实很简单,就是用一堆的重定义运算符来吓唬人,实现很多高大上的操作。
而iterator就是容器内定义的结构体,所以我们定义一个迭代器需要

Que::iterator it;

如果我们要遍历整个队列

Que q;
push_many_numbers(q);
for(Que::iterator it=q.begin();it!=q.end();++it)
{
  cout<<*it<<' '<<val[*it];
}

很多STL容器都是自带迭代器的,所以我们为什么还要自己写迭代器呢?
(回去问问为什么你要自己写结构体STL那么多好用的数据结构)
我们自己写迭代器,可以了解其中的思想,让我们的代码变得更加整洁,思路更加清晰。
而且STL也不是万能的,总有一天我们要自己写数据结构的时候,就难免会碰到这样的问题。
比如说这道题(说了这么多其实是为了纪念自己搞定了这道题)
[USACO21JAN] Dance Mooves G
他需要保存下来很多牛在一轮之中经过的位置。由于这个是不定的,所以用数组浪费空间让我很不爽我们用链表来储存
然后我就定义了迭代器。。。
(具体这道题怎么搞参考题解)

#include <cstdio>
#include <algorithm>
#include <cstring>

struct lce
{
	unsigned first,second;
	lce(unsigned a=0,unsigned b=0):first(a),second(b){}
	lce operator=(lce b)
	{
		first=b.first; second=b.second; return *this;
	}
};


template <typename T>
struct List
{
private:
	struct list
	{
		list *nxt, *pre;
		T dat;
		list() { pre=nxt=0x0; dat=0; }
		~list() { if(nxt) delete nxt; }
	};
	list *hd, *ed,*rst_end;
	unsigned sze;
public:
	List() { rst_end=ed=hd=new list; sze=0; }
	~List()
	{
		delete hd;
	}
	struct iterator
	{
		list *M_current;
		T operator *() const { return M_current->dat; }
		iterator operator ++() { M_current=M_current->nxt; return *this; }
		iterator operator --() { M_current=M_current->pre; return *this; }
		bool operator != (iterator a) const { return M_current!=a.M_current; }
		iterator(list *a=0x0) { M_current=a; }
	};
	inline iterator begin() const { return iterator(hd); }
	inline iterator end() const { return iterator(ed); }
	inline iterator rst() const { return iterator(rst_end?rst_end:ed); }
	inline unsigned size() const { return sze; }
	inline iterator append(T a,const bool k=0)
	{
		++sze;
		ed->dat=a;
		register const iterator It(ed);
		ed->nxt=new list;
		ed->nxt->pre=ed;
		ed=ed->nxt;
		if(k) rst_end=ed;
		return It;
	}
};

struct Graph
{
/// 此处略去1766字节
};

const int N=100001;

List <unsigned> pass_by[100001];

int n,k,a,b,ans[N];
unsigned *tmp;
long long int m;

inline void deal(unsigned,unsigned,unsigned,unsigned*);
inline void deal(unsigned,unsigned*);


int main()
{
	scanf("%d%d%lld",&n,&k,&m);
	Graph g(n);
	register const unsigned times_opt=m/k;
	register const unsigned rest_opt=m-k*times_opt;
	tmp=new unsigned[n+1];
	for(int i=1;i<=n;++i) pass_by[i].append(tmp[i]=i,rest_opt>=1);
	for(int i=1;i<=k;++i)
	{
		scanf("%d%d",&a,&b);
		pass_by[tmp[a]].append(b,rest_opt>=i); pass_by[tmp[b]].append(a,rest_opt>=i);
		tmp[a]^=tmp[b]^=tmp[a]^=tmp[b];
	}
	for(int i=1;i<=n;++i) g.add(*pass_by[i].begin(),*(--pass_by[i].end()));
	std::memset(tmp,0,sizeof(tmp[0])*(n+1));
	List<lce> sze;
	g.Tarjan(sze,tmp);
	for(List<lce>::iterator it=sze.begin();it!=sze.end();++it)
	{
		register unsigned x=(*it).first, cnt=(*it).second;
		std::memset(tmp,0,sizeof(tmp[0])*(n+1));
		if(cnt<=times_opt) deal(x,tmp);
		else deal(x,times_opt,rest_opt,tmp);
	}
	for(register int i=1;i<=n;++i) printf("%d\n",ans[i]);
	return 0;
}

inline void deal(unsigned s,unsigned* buf)
{
	register unsigned res=0,now=s;
	List<unsigned>::iterator ed;
	do
	{
		ed=pass_by[now].end();
		for(List<unsigned>::iterator it=pass_by[now].begin();it!=ed;++it)
		{
			if(buf[*it]) continue;
			++res; buf[*it]=true;
		}
		now=*--ed;
	}while(now!=s);
	now=s;
	do
	{
		ans[now]=res;
		now=*--pass_by[now].end();
	}while(now!=s);
}

inline void deal(unsigned s,unsigned cnt,unsigned rest,unsigned* buf)
{
	register unsigned res=0, now=s,xi=s;
	List<unsigned>::iterator ed;
	for(unsigned i=0;i<cnt;++i)
	{
		ed=pass_by[xi].end();
		for(List<unsigned>::iterator it=pass_by[xi].begin();it!=ed;++it) if(!(buf[*it]++)) ++res;
		xi=*--ed;
	}
	ed=pass_by[xi].rst();
	for(List<unsigned>::iterator it=pass_by[xi].begin();it!=ed;++it) if(!(buf[*it]++)) ++res;
	ans[s]=res;
	while(*--pass_by[now].end()!=s)
	{
		ed=pass_by[now].end();
		for(List<unsigned>::iterator it=pass_by[now].begin();it!=ed;++it) if(!(--buf[*it])) --res;
		now=*--ed;
		ed=pass_by[xi].end();
		for(List<unsigned>::iterator it=pass_by[xi].rst();it!=ed;++it) if(!(buf[*it]++)) ++res;
		xi=*--ed;
		ed=pass_by[xi].rst();
		for(List<unsigned>::iterator it=pass_by[xi].begin();it!=ed;++it) if(!(buf[*it]++)) ++res;
		ans[now]=res;
	}
}
posted @ 2021-12-03 13:41  IdanSuce  阅读(160)  评论(0编辑  收藏  举报