Narzędzia użytkownika

Narzędzia witryny


iterator

To jest stara wersja strony!


Iterator

Iterator jest uogolniona reprezentacja procesu poruszania sie po kontenerze, niezalezna od typu danych przechowywanych w kontenerze, ale takze od struktury danych samego kontenera.

Cechy iteratora:

  1. Mozliwosc wyluskania iteratora w celu uzyskania dostepu do wartosci, na ktora wskazuje. Jesli p jest iteratorem, to jest zdefiniowane wyrazenie *p.
  2. Mozliwosc przypisania jednego iteratora do drugiego. Jesli p i q sa iteratorami, to zdefiniowane jest p = q.
  3. Mozliwosc porownania jednego iteratora z drugim. Jesli p i q sa iteratorami, zdefiniowane sa wyrazenia p == q oraz p != q.
  4. Za pomoca iteratora mozna odwiedzic wszystkie elementy kontenera. Dla iteratora p zdefiniowane sa instrukcje p++ oraz ++p.

Przykladowy iterator

/* klasa wezla kontenera */
template <class Type>
struct Node
{
	Type item_;
	Node* next_;
};
 
template <class Type>
class iterator
{
private:
	Node<Type>* ptr_;
 
public:
	iterator(): ptr_(0) {}
	iterator( Node<Type>* n ): ptr_(n) {}
 
	/* operator wyluskania wartosci, na ktora wskazuje iterator */
	Type operator* () { return ptr_->item_; }
 
	/* preinkrementacja - ++iter */
	/* odwiedza nastepny element w kontenerze */
	iterator& operator++()
	{
		ptr_ = ptr_->next_;
 
		return *this;
	}
 
	/* postinkrementacja - iter++ */
	iterator& operator++(int)
	{
		iterator tmp = *this;
		ptr_ = ptr_->next_;
 
		return tmp;
	}
 
	/* operator porownania == */
	/* zwraca true jesli iteratory wskazuja na ten sam element */
	bool operator== ( const iterator& i )
	{
		if ( ptr_ == i.ptr_ )
			return true;
 
		return false;
	}
 
	/* operator nierownosci != */
	bool operator!= ( const iterator& i )
	{
		return !( *this == i );
	}
 
	/* operator przypisania = */
	iterator& operator= ( const iterator& i )
	{
		ptr_ = i.ptr_;
 
		return *this;
	}
};

Rodzaje iteratorow

Istnieje kilka typów iteratorów, w zależności od udostępnianych operacji:

iterator wejściowy
  • wyłuskiwanie do odczytu
  • operacje ++i oraz i++
iterator wyjściowy
  • wyłuskiwanie do zapisu
  • operacje ++i oraz i++
iterator postępujący
  • operacje iteratorów wejściowego oraz wyjściowego
iterator dwukierunkowy
  • operacje iteratoraiteratorao
  • operacje -—i oraz i-— umożliwiające poruszanie się po kontenerze w dwóch kierunkach
iterator dostępu swobodnego (RandomAccessIterator)
  • operacje iteratora dwukierunkowego
  • operacja i + n, czyli wskazanie na n-ty element po elemencie, na który wskazuje i
  • operacja n + i (to samo co i + n)
  • operacja i - n, czyli wskazanie na n-ty element przed elementem, na który wskazuje i
  • i += n (to samo co i = i + n) oraz i -= n ( i = i - n )
  • operator i[], czyli *(i + n)
  • i - j, czyli wartość takiego n, ze i = j + n
  • i < j, które jest prawdziwe gdy j - i > 0
  • i > j, które jest prawdziwe gdy j < i
  • i >= j (analogicznie i ⇐ j), które jest prawdziwe gdy !(i < j)

Rożne funkcje operujące na kontenerach wymagają iteratora spełniającego pewne właściwości, np. prototyp funkcji sort ma postać:

template <class RandomAccessIterator>
 void sort ( RandomAccessIterator first, RandomAccessIterator last );

- czyli podawane argumenty muszą udostępniać operacje i + n, i - n itp.

Iteratory w bibliotece standardowej

W bibliotece STL kazda klasa kontenerowa posiada definicje odpowiedniego iteratora klasy. Dla jednej moze byc to wskaznik (ktory rowniez moze byc iteratorem, jako ze posiada wszystkie wymagane wlasciwosci), dla innej moze byc to obiekt. Ponadto klasy te posiadaja metody begin() oraz end(), ktore zwracaja iteratory na pierwszy element kontenera oraz na pozycje za ostatnim elementem.

Iteratory dostepu swobodnego:
  • T* (wskaznik)
  • vector<T>::iterator
  • vector<T>::const_iterator
  • deque<T>::iterator
  • deque<T>::const_iterator
Iteratory dwukierunkowe:
  • list<T>::iterator
Iteratory postepujace:
  • hash_set<T>::iterator

Korzystanie z iteratorow

/* Przyklad - korzystanie z iteratorow */
#include <vector>
#include <list>
#include <iostream>
#include <algorithm>
 
int main () {
 
	using namespace std;
 
	vector<int> v;
	v.push_back ( 3 );
	v.push_back ( 2 );
	v.push_back ( 7 );
	v.push_back ( 5 );
 
	list<int> l;
	l.push_back ( 3 );
	l.push_back ( 2 );
	l.push_back ( 7 );
	l.push_back ( 5 );
 
	/* przegladanie kontenera vector za pomoca iteratora */
	vector<int>::iterator vi;
 
	cout << "vector: ";
	for ( vi = v.begin(); vi != v.end(); ++vi ){
		cout << *vi;
	}
	cout << endl;
 
	/* przegladanie kontenera list za pomoca iteratora */
	/* identycznie jak w przypadku przegladania vectora, choc implementacja kontenerow jest inna */
	list<int>::iterator li;
 
	cout << "list: ";
	for ( li = l.begin(); li != l.end(); ++li ){
		cout << *li;
	}
	cout << endl;
 
	/* iterator klasy vector jest typu RandomAccessIterator, mozna wiec uzyc ich do funkcji sort */
	sort ( v.begin(), v.end() );
 
	cout << "sorted vector: ";
	for ( vi = v.begin(); vi != v.end(); ++vi ){
		cout << *vi;
	}
	cout << endl;
 
	/* iterator klasy list jest typu dwukierunkowego, a wiec instrukcja: */
	// sort ( l.begin(), l.end() ); 
	/* wywola blad kompilacji z komunikatem, ze list<T>::iteator nie udostepnia operacji - */
 
	return 0;
}
iterator.1229044890.txt.gz · ostatnio zmienione: 2008/12/12 02:21 przez gierek