Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как создать итератор для своего контейнера 
V
    Опции темы
youriy86
Дата 1.2.2011, 00:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 28.1.2011

Репутация: нет
Всего: нет



Всем привет. 
У меня следующая задача:
Мне нужно создать контейнер строк hash_set, организованный в виде хеш-таблицы. Этот контейнер должен определить свой итератор, который может перемещаться по элементам контейнера в определенном порядке.
Подскажите плиз, как вообще определить итератор?
PM MAIL   Вверх
mes
Дата 1.2.2011, 11:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(youriy86 @  31.1.2011,  23:54 Найти цитируемый пост)
 как вообще определить итератор? 

написать свой класс для этого smile


--------------------
PM MAIL WWW   Вверх
baldina
Дата 1.2.2011, 12:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Цитата(youriy86 @  1.2.2011,  00:54 Найти цитируемый пост)
Этот контейнер должен определить свой итератор

кому он должен? видимо, такое желание продиктовано некоторыми внешними условиями. например, требованием сделать контейнер совместимым с алгоритмами STL. тогда нужно создать итератор в стиле STL - определить для него соответствующие типы и операции.

вообще, итератор - специальный объект, позволяющий получать доступ к элементам коллекции. возможности итератора напрямую связаны с организацией коллекции. например, итератор доступа к элементам массива позволяет произвольный доступ (по индексу), а к элементам списка - последовательный.
в некотором смысле понятие итератора является обобщением указателя в С/С++, и операции итератора делают похожими на операции с указателями:
если I - тип итератора
I iter - итератор
*iter - элемент коллекции
++iter; --iter - перестановка итератора (последовательный доступ)
iter += n; iter -= n - перестановка итератора (произвольный доступ)
в STL контейнеры имеют методы begin() и end(), возвращающие итераторы. пример:
Код

std::vector<int> v;
// вывести все элементы v
for (std::vector::iterator i = v.begin(); i != v.end(); ++i)
  std::cout << *i;

как реализовать итератор? это зависит от структуры данных, но ясно, что итератор должен внутри себя хранить некую ссылку на текущий элемент коллекции
в простейшем виде может быть так (не является полностью совместимым с STL):
Код

template <typename T, size_t N>
class Array {
  T data[N];
 public:
  struct iterator {
    T *ptr;
    iterator (T* ptr_=0) : ptr(ptr_) {}
    T& operator*() { return *ptr; }
    T* operator->() { return ptr; }
    T* operator++() { return ++ptr; }
    T* operator--() { return --ptr; }
    bool operator==(const iterator& other) const { return ptr == other.ptr; }
    bool operator!=(const iterator& other) const { return !(*this == other); }
  };

  size_t size() const { return N; }
  iterator begin () { return data; }
  iterator end () { return data+N; }
};

тут пример использования
PM MAIL   Вверх
youriy86
Дата 1.2.2011, 13:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 28.1.2011

Репутация: нет
Всего: нет



То есть получается итератор я должен завести внутри класса?

Добавлено через 12 минут и 41 секунду
Вообще мне нужно реализовать хеш-таблицу и сделать у нее итератор, пробегающий по всем элементам. 
Как это сделать я вообще не понимаю даже с использованием предложенного примера, у меня же элементы в хэш-таблице хранятся не последовательно а в корзинах, в каждой корзине их может быть разное число. Каким образом можно организовать этот итератор?
Код

class HashSet {
private:
    float fAlpha;
    int fCountElements;
    Backets fBackets;
    int Hash(char* aElement);
    void AddElement(char* aElement);
public:
    HashSet();
    char* Element(int aIndB, int aIndEl) { return fBackets[aIndB][aIndEl]; }
    int GetCountBacketEl(int aIndB) { return fBackets[aIndB].size(); }
    int GetCountBackets() { return fBackets.size(); }
    void Print();
    void Add(char* aElement);
};


Добавлено через 14 минут и 14 секунд
У меня задание по STL просто. И в задаче нужно чтобы этот итератор мог пройтись по всем элементам hash_set от начала до конца, я так понимаю например чтобы можно было распечатать все эти элементы используя итератор.
PM MAIL   Вверх
baldina
Дата 1.2.2011, 16:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Цитата(youriy86 @  1.2.2011,  13:49 Найти цитируемый пост)
То есть получается итератор я должен завести внутри класса?

необязательно. у меня он внутри класса по двум простым соображениям
1. без класса итератор не имеет смысла
2. не стоит засорять глобальное пространство имен
3. лень лишний раз template писать

хотя понятно, что 
Код

template <typename T>
struct iterator {
    T *ptr;
    iterator (T* ptr_=0) : ptr(ptr_) {}
    T& operator*() { return *ptr; }
    T* operator->() { return ptr; }
    T* operator++() { return ++ptr; }
    T* operator--() { return --ptr; }
    bool operator==(const iterator& other) const { return ptr == other.ptr; }
    bool operator!=(const iterator& other) const { return !(*this == other); }
  };

подходит под множество типов коллекций, хранящих T последовательно (в массиве)

с другой стороны, это слишком упрощенный пример, не учитывающий множества ситуаций. это скорее учебный псевдокод (хоть и работающий)
PM MAIL   Вверх
bsa
Дата 1.2.2011, 16:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



youriy86, чтобы сделать STL совместимый итератор изучи сначала документацию на класс std::iterator.

Цитата(youriy86 @  1.2.2011,  14:49 Найти цитируемый пост)
Как это сделать я вообще не понимаю даже с использованием предложенного примера, у меня же элементы в хэш-таблице хранятся не последовательно а в корзинах, в каждой корзине их может быть разное число. Каким образом можно организовать этот итератор?

Представляем контейнер в виде дерева. У дерева есть узлы и связи. У каждого узла есть связь с родителем и могут быть связи с дочерними узлами (могут быть вариации на тему, есть ли данные в узлах, имеющих дочерние узлы, или нет). Так вот, у тебя есть указатель на какой-то узел (итератор), чтобы получить указатель на следующий ты должен:
1. если есть дочерние узлы, то переход к первому из них
2. если нет дочерних, то рекурсивный возврат к следующему брату текущего узла
PM   Вверх
baldina
Дата 1.2.2011, 16:09 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Цитата(youriy86 @  1.2.2011,  13:49 Найти цитируемый пост)
у меня же элементы в хэш-таблице хранятся не последовательно а в корзинах, в каждой корзине их может быть разное число

ну значит итератор должен хранить текущую корзину и индекс в корзине. это чуть сложнее, но не смертельно
Код

struct HashSet_iterator {
 int aIndB;
 int aIndEl;
 Backets& fBackets;
 ...
 
 char* operator*() { return fBackets[aIndB][aIndEl]; }
 HashSet_iterator& operator++() { 
  ++aIndEl; 
  if (aIndEl == fBackets[aIndB].size())
  {
     aIndEl = 0;
     ++aIndB;
  }
  return *this;
 }
  ...
};


Добавлено @ 16:11
Цитата(bsa @  1.2.2011,  16:06 Найти цитируемый пост)
Представляем контейнер в виде дерева.

для HashSet youriy86 это чересчур smile

Это сообщение отредактировал(а) baldina - 1.2.2011, 16:13
PM MAIL   Вверх
youriy86
Дата 1.2.2011, 18:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 28.1.2011

Репутация: нет
Всего: нет



Привожу код, который у меня получился. Релизация AddElement и остальных функций в .cpp. Подумал отношения к делу не имеет, поэтому не привожу.
Код

#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;

typedef vector<char*> Backet;
typedef vector<Backet> Backets;

class HashSet {
private:
    float fAlpha;
    int fCountElements;
    Backets fBackets;
    int Hash(char* aElement);
    void AddElement(char* aElement);
public:

    struct HashSet_iterator {
    private:
        int fIndB;
        int fIndEl;
        Backets& fBackets;
    public:
        HashSet_iterator(Backets aBackets,int aIndB, int aIndEl) : fBackets(aBackets), fIndB(aIndB), fIndEl(aIndEl) {}
        HashSet_iterator operator=(HashSet_iterator& other) { fBackets = other.fBackets; fIndB = other.fIndB; fIndEl = other.fIndEl; return *this; }
        char* operator*() { return fBackets[fIndB][fIndEl]; }
        HashSet_iterator& operator++() { 
            ++fIndEl; 
            if (fIndEl == fBackets[fIndB].size())
            {
                fIndEl = 0;
                ++fIndB;
            }
            return *this;
        }
        bool operator==(const HashSet_iterator& other) const { return fBackets == other.fBackets; }
        bool operator!=(const HashSet_iterator& other) const { return !(*this == other); }
    };

    HashSet();
    char* Element(int aIndB, int aIndEl) { return fBackets[aIndB][aIndEl]; }
    int GetCountBacketEl(int aIndB) { return fBackets[aIndB].size(); }
    int GetCountBackets() { return fBackets.size(); }
    void Print();
    void Add(char* aElement);
    HashSet_iterator begin() { return HashSet_iterator(fBackets,0,0); }
    HashSet_iterator end() { return HashSet_iterator(fBackets,fBackets.size() - 1, fBackets[fBackets.size() - 1].size() - 1); } 
};


Вроде бы компилируется, но следующая запись ничего не выдает:

Код

HashSet* vHS = new HashSet();
    vHS->Add("a");
    vHS->Add("b");
    vHS->Add("c");
for (HashSet::HashSet_iterator it = vHS->begin(); it != vHS->end(); ++it)
        cout<<*it<<"\n";


Это сообщение отредактировал(а) youriy86 - 1.2.2011, 19:32
PM MAIL   Вверх
baldina
Дата 1.2.2011, 19:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Код

HashSet_iterator(Backets& aBackets,int aIndB, int aIndEl) : 
  fBackets(aBackets), 
  fIndB(aIndB), 
  fIndEl(aIndEl) 
{}

Код

bool operator==(const HashSet_iterator& other) const { 
  return 
    fBackets == other.fBackets && 
    fIndB == other.fIndB && 
    fIndEl == other.fIndEl; 
}

Код

HashSet_iterator end() { 
  return 
    HashSet_iterator (fBackets, fBackets.size(), fBackets[fBackets.size()-1].size()-1); 
} 



Это сообщение отредактировал(а) baldina - 1.2.2011, 20:02
PM MAIL   Вверх
youriy86
Дата 1.2.2011, 20:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 28.1.2011

Репутация: нет
Всего: нет



ОМГ заработало!!!!!!!!!!!! Я тя обожаю!!!! Спасибо большое!!!!!!!!!!!
PM MAIL   Вверх
youriy86
Дата 21.12.2011, 16:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 28.1.2011

Репутация: нет
Всего: нет



Выкладываю по просьбе одного из форумчан

Присоединённый файл ( Кол-во скачиваний: 43 )
Присоединённый файл  cpp.rar 1,33 Kb
PM MAIL   Вверх
boostcoder
Дата 21.12.2011, 16:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 20
Всего: 110



Цитата(youriy86 @  1.2.2011,  20:36 Найти цитируемый пост)
Я тя обожаю!

что бы это означало? smile 
PM WWW   Вверх
borisbn
Дата 21.12.2011, 17:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Цитата(youriy86 @  1.2.2011,  20:36 Найти цитируемый пост)
Я тя обожаю!

Может, всё-таки, ты хотел попросить кого-нибудь плюсануть baldina (поднять репутацию) ?


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
kolaspirit
Дата 21.12.2011, 22:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 7.12.2011

Репутация: нет
Всего: нет



Спасибо за исходники!
Кому интересно, могу предложить свою реализацию hash_set на основе хэш-таблицы.
P.S. В моей реализации используются лямбда-функции, и она без циклов for и while (так было необходимо сделать по заданию). Для быстродействия использованы стандартные алгоритмы STL.

Присоединённый файл ( Кол-во скачиваний: 32 )
Присоединённый файл  hash_set.rar 2,39 Kb
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0620 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.