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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> собственный клас вектор 
V
    Опции темы
toxx
Дата 31.3.2010, 18:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Решил написать хотя бы похожий на класс вектор свой класс
Код

template <class T>
class Vector
{
    T* V;
    int n;
public:
    Vector(int=0);
    Vector(const Vector&);
    int size(){return n;}
    int begin(){return 0;}
    int end(){return n;}
    void resize(int);
    Vector& erase(int);
    ~Vector(){delete[] V;}
    T& operator[](int i){return V[i];}
};

Хочется узнать, что нужно еще сделать, чтобы метод erase() был похож на erase() из вектора.
Просто,работая с деревом(тема)
При замене на свой вектор появляются многочисленные ошибки памяти(bad_alloc и другие)
erase
Код

template <class T>
Vector<T>& Vector<T> ::erase(int k)
{
    k-=1;
    Vector<T> buf=*this;
    for(int i=0;i<n;i++)
    {
        if(i!=k)V[i]=buf[i];
        else 
        {
            V[i]=buf[i+1];
            k++;
        }
    }
    n-=1;
    V=new T[n];
    for(int i=0;i<n;i++)
        V[i]=buf[i];
    return *this;
}

конструктор копировщик
Код

Vector<T>::Vector(const Vector& Vect)
{
    n=Vect.n;
    V=new T[n];
    for(int i=0;i<n;i++)
        V[i]=Vect.V[i];
}



Это сообщение отредактировал(а) toxx - 1.4.2010, 17:47
PM MAIL   Вверх
ИванМ
Дата 31.3.2010, 20:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



что делает твой метод erase я так и не понял, а конструктор копирования вроде правильный
PM MAIL   Вверх
toxx
Дата 31.3.2010, 20:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(ИванМ @ 31.3.2010,  20:15)
что делает твой метод erase я так и не понял, а конструктор копирования вроде правильный

По идее должен удалять к-й элемент массива, нумерация 1 2 ...
PM MAIL   Вверх
ИванМ
Дата 31.3.2010, 20:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(toxx @  31.3.2010,  18:40 Найти цитируемый пост)
for(int i=0;i<n;i++)
    {
        if(i!=k)V[i]=buf[i];
        else 
        {
            V[i]=buf[i+1];
            k++;
        }
    }

зачем нужен весь этот код если потом ты массив V все равно пересоздаешь, причем не удаляя старый вариант.

Цитата(toxx @  31.3.2010,  18:40 Найти цитируемый пост)
V=new T[n];


PM MAIL   Вверх
toxx
Дата 31.3.2010, 20:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



ИванМ
Ну я перекопировал элементы старого массива 
потом уменьшил размерность старого массива
Код

 n-=1;

И перекопирую уже в новый
Может быть так лучше будет, с точки зрения вашего совета?
Код

Vector<T>& Vector<T> ::erase(int k)
{
    k-=1;
    Vector<T> buf=*this;
    for(int i=0;i<n;i++)
    {
        if(i!=k)V[i]=buf[i];
        else 
        {
            V[i]=buf[i+1];
            k++;
        }
    }
    n-=1;
    delete(V);
    V=new T[n];
    for(int i=0;i<n;i++)
        V[i]=buf[i];
    delete(buf);
    buf=NULL;
    return *this;
}

Чето намудрил с operator delete он отказывается удалять )

Это сообщение отредактировал(а) toxx - 31.3.2010, 20:39
PM MAIL   Вверх
ИванМ
Дата 31.3.2010, 20:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



toxx, ты перекопировал элементы массива V из объекта buf  в объект this странным кривым образом, а потом еще вдобавок удалил весь массив V объекта this и заново его создал. зачем тогда вообще предыдущая операция была нужна?

Добавлено через 1 минуту и 46 секунд
Цитата(toxx @  31.3.2010,  20:32 Найти цитируемый пост)
delete(buf);
    buf=NULL;

и это что означает? delete это операция, применимая к указателю, а не значению. и к нулю твой тип приравнять нельзя. 
PM MAIL   Вверх
toxx
Дата 31.3.2010, 20:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



ой, понял что вы имеете ввиду только со 2го раза, вот сделал вродебы
Код

Vector<T>& Vector<T> ::erase(int k)
{
    k-=1;
    Vector<T> buf=*this;
    for(int i=0;i<n;i++)
    {
        if(i!=k)V[i]=buf[i];
        else 
        {
            buf[i]=V[i+1];
            k++;
        }
    }
    n-=1;
    //
    delete V;
    V=new T[n];
    for(int i=0;i<n;i++)
        V[i]=buf[i];
    //delete buf;
    //buf=NULL;
    return *this;
}


Да, вот с этим
Код

delete(buf);
    buf=NULL;


проблема, щас переделываю...
PM MAIL   Вверх
ИванМ
Дата 31.3.2010, 21:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



toxx, нет, вы так ничего и не поняли. Остальной код вы сами писали? Странно, если сами.
PM MAIL   Вверх
toxx
Дата 31.3.2010, 22:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(ИванМ @ 31.3.2010,  21:52)
toxx, нет, вы так ничего и не поняли. Остальной код вы сами писали? Странно, если сами.

Код

Vector<T>& Vector<T> ::erase(int k)
{
    k-=1;
    Vector buf=*this;
    for(int i=0;i<n;i++)
    {
        if(i!=k)buf[i]=V[i];
        else 
        {
            buf[i]=V[i+1];
            k++;
        }
    }
    n-=1;
    delete V;
    V=new T[n];
    for(int i=0;i<n;i++)
        V[i]=buf[i];
    return *this;
}


Все писал сам, в книге только структура дана была и конструктор(не копировщик).
Я просто этим первый раз занимаюсь, отсюда такие проблемы.
может быть вы имели ввиду вот эту строчку:
Код

Vector buf=*this;

я уже не знаю почему я не правильно вас понял...

Это сообщение отредактировал(а) toxx - 31.3.2010, 23:07
PM MAIL   Вверх
ИванМ
Дата 1.4.2010, 15:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Давайте я вам напишу алгоритм по шагам.
1 пункт у вас правильный: создаете копию этого объекта this.
Код

Vector buf=*this;

2 пункт. Сдвигаете элементы созданного вектора buf влево, начиная с нужного символа (не забывая, что нельзя выходить за границу массива, это у вас не предусмотрено)
3 пункт. Удаляете массив вектора this и создаете его заново, с кол-вом элементов меньшим на единицу
можно как у вас
Код

n-=1;
    delete V;
    V=new T[n];

4 пункт. Копируете элементы из измененного вектора buf в массив вектора this, исключая последний элемент в buf
Вот и все. А у вас там каша какая-то

PM MAIL   Вверх
toxx
Дата 1.4.2010, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

4 пункт. Копируете элементы из измененного вектора buf в массив вектора this, исключая последний элемент в buf
Вот и все. А у вас там каша какая-то


Я вродебы таким вот образом скопировал элементы buf в массив V( как я понял V, это и есть this?)
Код

for(int i=0;i<n;i++)
    V[i]=buf[i];


Или нужно писать вместо моего копирования
Код

..............................
    for(int i=0;i<n;i++)
        V[i]=buf[i];
    return *this;
}

вот это
Код

.............................
for(int i=0;i<n;i++)
    (this*)[i]=buf[i];
}




Это сообщение отредактировал(а) toxx - 1.4.2010, 16:17
PM MAIL   Вверх
ИванМ
Дата 1.4.2010, 16:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



не заметил последний исправленный вариант
если вот этот участок подправить, то все будет хорошо:
Цитата(toxx @  31.3.2010,  22:59 Найти цитируемый пост)
 for(int i=0;i<n;i++)
    {
        if(i!=k)buf[i]=V[i];
        else 
        {
            buf[i]=V[i+1];
            k++;
        }
    }


PM MAIL   Вверх
toxx
Дата 1.4.2010, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Добавил условие выхода за границу массива
Код

for(int i=0;i<n;i++)
{
    if(i!=k)buf[i]=V[i];
    else if((i+1)<n)
    {
        buf[i]=V[i+1];
        k++;
    }
}

В итоге должно быть что-то такое?
Код

Vector<T>& Vector<T> ::erase(int k)
{
    k--;
    if(k>=n) 
    {
        cout<<"out of range"<<endl;
        return *this;
    }
    Vector buf=*this;
    for(int i=0;i<n;i++)
    {
        if(i!=k)buf[i]=V[i];
        else if((i+1) <n)
        {
            buf[i]=V[i+1];
            k++;
        }
    }
    n--;
    delete V;
    V=new T[n];
    for(int i=0;i<n;i++)
        (*this)[i]=buf[i];
}


Это сообщение отредактировал(а) toxx - 1.4.2010, 16:55
PM MAIL   Вверх
ИванМ
Дата 1.4.2010, 16:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



все гораздо проще. на этом этапе можно обойтись с одним объектом - buf
просто проходите по элементам buf по циклу начиная с k и заканчивая n-2
и приравниваете текущей элемент следующему
и все
PM MAIL   Вверх
toxx
Дата 1.4.2010, 17:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(ИванМ @ 1.4.2010,  16:39)
все гораздо проще. на этом этапе можно обойтись с одним объектом - buf
просто проходите по элементам buf по циклу начиная с k и заканчивая n-2
и приравниваете текущей элемент следующему
и все

Вот что получил функция значительно уменьшилась...
Код

Vector<T>& Vector<T> ::erase(int k)
{
    if(k>=n||k<0) 
    {
        cout<<"index out of range"<<endl;
        return *this;
    }
    Vector buf=*this;
    n--;
    delete V;
    V=new T[n];
    for(int i=0;i<n;i++)
    if(i!=k)(*this)[i]=buf[i];
    else 
    {
        (*this)[i]=buf[i+1];
        k++;
    }
}


Это сообщение отредактировал(а) toxx - 1.4.2010, 17:11
PM MAIL   Вверх
ИванМ
Дата 1.4.2010, 17:37 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Код

Vector<T>& Vector<T> ::erase(int k)
{
    if(k>=n||k<0) 
    {
        cout<<"index out of range"<<endl;
        return *this;
    }
    Vector buf=*this;
    for(int i=k;i<n-1;i++)
        buf[i]=buf[i+1];
    n--;
    delete V;
    V=new T[n];
    for(int i=0;i<n;i++)
        (*this)[i]=buf[i];
    return *this;
}

PM MAIL   Вверх
toxx
Дата 1.4.2010, 17:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



ИванМ
Первый раз когда я писал предыдущее своё сообщение я так вас и понял, но 
потом подумал может быть вы опять не это от меня хотите и увидел, что
проще это с одним циклом for...

А вот еще метод resize(int) у вектора он 
1.перевыделяет количество памяти массива на нужную?
2.и копирует все элементы предыдущего массива и если размер больше он лишние элементы зануляет?(если размер больше предыдущего массива)


Это сообщение отредактировал(а) toxx - 1.4.2010, 18:03
PM MAIL   Вверх
ИванМ
Дата 1.4.2010, 18:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(toxx @  1.4.2010,  17:58 Найти цитируемый пост)
1.перевыделяет количество памяти массива на нужную?

да

Цитата(toxx @  1.4.2010,  17:58 Найти цитируемый пост)
и копирует все элементы предыдущего массива и если размер больше он лишние элементы зануляет? 

это зависит от разработчика
самое оптимально это да, занулить
PM MAIL   Вверх
toxx
Дата 1.4.2010, 18:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



ИванМ
Код

void Vector<T>::resize(int k)
{
    delete[] V;
    n=k;
    V=new T[n];
    for(int i=0;i<n;i++)
        (*this)[i]=0;
}


вот этого будет достаточно?

Это сообщение отредактировал(а) toxx - 1.4.2010, 18:05
PM MAIL   Вверх
ИванМ
Дата 1.4.2010, 18:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



toxx, нет, надо еще сохранить элементы, которые были до этого, меньшие k
PM MAIL   Вверх
toxx
Дата 1.4.2010, 18:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Код

void Vector<T>::resize(int k)
{
    Vector buf=*this;
    delete[] V;
    n=k;
    V=new T[n];
    for(int i=0;i<n;i++)
    if(i<buf.size())(*this)[i]=buf[i];
        else (*this)[i]=0;
}


Вот, протестировал вроде бы работает.
PM MAIL   Вверх
ИванМ
Дата 1.4.2010, 18:40 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



toxx, да, вроде правильно.
PM MAIL   Вверх
toxx
Дата 1.4.2010, 18:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(ИванМ @ 1.4.2010,  18:40)
toxx, да, вроде правильно.

ИванМ
Спасибо за подсказки.
PM MAIL   Вверх
bsa
Дата 2.4.2010, 11:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



toxx, вообще-то твой код метода resize() довольно замысловат и далеко не оптимален.
Ты должен, создать новый объект нового размера, скопировать туда остающиеся данные из старого вектора. Затем, ты должен обменять поля V и n этих объектов.
По-хорошему, вектор вообще нужно делать с использованием размещающего new, чтобы при уменьшении размера не было необходимости освобождать память и копировать оставшиеся данные. А при увеличении - увеличивать несколько больше, чем требуется, чтобы было меньше этих затратных операций (например, если вызывать push для stl-вектора, то выделенная память (capacity) будет выделсять так: 2, 4, 8, 16, 32, 64, 128, 256, ...; таким образом, нетрудно заметить, что для 256 элементов память будет перевыделяться только 8 раз, а по твоему алгоритму - все 512, если использовать resize).

Это сообщение отредактировал(а) bsa - 2.4.2010, 11:37
PM   Вверх
toxx
Дата 2.4.2010, 13:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(bsa @ 2.4.2010,  11:36)
toxx, вообще-то твой код метода resize() довольно замысловат и далеко не оптимален.
Ты должен, создать новый объект нового размера, скопировать туда остающиеся данные из старого вектора. Затем, ты должен обменять поля V и n этих объектов.
По-хорошему, вектор вообще нужно делать с использованием размещающего new, чтобы при уменьшении размера не было необходимости освобождать память и копировать оставшиеся данные. А при увеличении - увеличивать несколько больше, чем требуется, чтобы было меньше этих затратных операций (например, если вызывать push для stl-вектора, то выделенная память (capacity) будет выделсять так: 2, 4, 8, 16, 32, 64, 128, 256, ...; таким образом, нетрудно заметить, что для 256 элементов память будет перевыделяться только 8 раз, а по твоему алгоритму - все 512, если использовать resize).

Если это будет оптимально, то я попробую переделать щас )Тогда у меня пара вопросов:

1.выделение больше это не плохо?(например мне надо 129 а выделяется 256...)
2.Это так хорошо компенсируется количеством вызовов resize?

Просто нас всё учат сколько нужно столько и выдели)Лишнего не выделять, а то приводятся примеры с размерностью массивов не 10 а в энное количество раз больше.


Это сообщение отредактировал(а) toxx - 2.4.2010, 13:37
PM MAIL   Вверх
bsa
Дата 2.4.2010, 14:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(toxx @  2.4.2010,  13:35 Найти цитируемый пост)
Просто нас всё учат сколько нужно столько и выдели)Лишнего не выделять, а то приводятся примеры с размерностью массивов не 10 а в энное количество раз больше.
Есть рамки разумного. Конечно, если ты заполняешь массив путем 513 вызовов метода push, то любой алгоритм будет работать неоптимально. Или сильно тормозить, или выделит память под лишние 511 элементов. Учитывая нынешние объемы памяти, второе предпочтительней первого.
Но в любом случае, реализация resize через 1 полное и оно частичное копирование всего массива - это перебор. Достаточно одного "частичного".
PM   Вверх
toxx
Дата 2.4.2010, 16:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(bsa @ 2.4.2010,  14:40)
Цитата(toxx @  2.4.2010,  13:35 Найти цитируемый пост)
Просто нас всё учат сколько нужно столько и выдели)Лишнего не выделять, а то приводятся примеры с размерностью массивов не 10 а в энное количество раз больше.
Есть рамки разумного. Конечно, если ты заполняешь массив путем 513 вызовов метода push, то любой алгоритм будет работать неоптимально. Или сильно тормозить, или выделит память под лишние 511 элементов. Учитывая нынешние объемы памяти, второе предпочтительней первого.
Но в любом случае, реализация resize через 1 полное и оно частичное копирование всего массива - это перебор. Достаточно одного "частичного".

Да это верно...=)
Только разберусь со своим деревом(опять чето не удаляет ничего), и попробую реализовать,что вы посоветовали...
PM MAIL   Вверх
mes
Дата 2.4.2010, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(toxx @  2.4.2010,  12:35 Найти цитируемый пост)
Просто нас всё учат сколько нужно столько и выдели)Лишнего не выделять, а

Вектор не может знать сколько нужно, поэтому он должен подбирать средне-оптимальную стратегию,
но при этом должен оставлять возможность "ручного" управления.
Т.е. если программист в курсе что у него будет именно 129 элементов, он может сделать vector.reserve (129), и спокойно через push добавлять элементы, не испытывая (лишней) переаллокации.
Также хочу отметить, что это плохое решение - выбирать один контейнер на все случаи жизни.. 
Вектор удобен в случае рандомного доступа к элементам, но для "произвольного" наполнения он не эффективен. 
Но и тут не все так плохо, как кажется.
Программист может для наполнения использовать например очередь, которая не будет столь необдуманно копировать содержимое, как вектор, а также не будет столь жадная на память как список. Ну а как наполнение закончено и необходим быстрый рандомный доступ и линейное расположение, то можно за один присест, перекопировать очередь в вектор.

Исходя из вышесказнного считаю, что создание своего вектора иначе, чем для учебных целей, плохая затея.. 




--------------------
PM MAIL WWW   Вверх
ИванМ
Дата 2.4.2010, 17:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



mes, ты все говоришь правильно. Но думаю в данном случае это избыточная информация. Студенту просто нужно написать программу как их учили. И с этой задачей toxx справился.
Но твои советы могут служить в продолжении темы, для самообразования.
PM MAIL   Вверх
mes
Дата 2.4.2010, 17:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



toxx, как совет по оформлению кода : используйте пустые строчки для разделения логических блоков функции,
а также не скупитесь на пробелы и ясные имена хотя бы для не локальных переменных.
т.е. вместо :
Код

void Vector<T>::resize(int k)
{
    Vector buf=*this;
    delete[] V;
    n=k;  
    V=new T[n];
    for(int i=0;i<n;i++)
    if(i<buf.size())(*this)[i]=buf[i];
        else (*this)[i]=0;
}

примерно так :
Код

void Vector<T>::resize(int new_size)
{
    Vector buf = *this;
    delete[] V;

    m_size = new_size; 
    V = new T[m_size];

    for(int i=0; i<m_size; ++i )
      if (i<buf.size())  (*this)[i] = buf[i];
      else               (*this)[i] = 0;
}


и Вам будет легче, и у форумчан глаза целей.
smile
P.S. содержимое  использованно только для примера оформления, ибо оно далеко от приемлегого..
smile


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


Опытный
**


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

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



bsa
Вродебы сделал чего-то сделал
Класс
Код

class Vector
{
    T* V;
    int n;
    int capacity;
public:
    Vector(int=0);
    Vector(const Vector&);
    int size(){return n;}
    int begin(){return 0;}
    int capacit(){return capacity;}
    int end(){return n;}
    Vector resize(int);
    Vector& erase(int);
    void push_back(T);
    ~Vector(){delete[] V;}
    T& operator[](int i){return V[i];}
};

метод
Код

Vector<T> Vector<T>::resize(int k)
{
    if(capacity>k||k<0) return *this;
    else 
    {
        while(k>capacity)
            capacity*=2;
        Vector buf=*this;
        delete[] V;
        n=k;
        V=new T[capacity];
        for(int i=0;i<capacity;i++)
        if(i<buf.size())(*this)[i]=buf[i];
            else (*this)[i]=0;
    }
    return *this;
}

Изменил конструктор
Код

Vector<T>::Vector(int k)
{
    capacity=1;
    while(k>capacity)
        capacity*=2;
    n=k;
    V=new T[capacity];
}



mes
Ну я уже взялся, тем более я взялся, чтобы понять как работают классы как перекгружать и т.д. 
Да конечно я буду использовать свой вектор тока в лабах, но думаю мне пойдет на пользу если я сделаю грамотно всё.

PM MAIL   Вверх
mes
Дата 2.4.2010, 18:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(ИванМ @  2.4.2010,  16:55 Найти цитируемый пост)
Но думаю в данном случае это избыточная информация. 

А мне показалось, что как раз сейчас самое время показать, как обойти недостатки вектора, и чтоб пришло понимание, что неоптимальность вектора это не вина вектора, а неправильный выбор программистом либо контейнера либо алгоритма использования  smile

Добавлено @ 18:04
Цитата(toxx @  2.4.2010,  17:02 Найти цитируемый пост)
я взялся, чтобы понять как работают классы как перекгружать и т.д. Да конечно я буду использовать свой вектор тока в лабах, но думаю мне пойдет на пользу если я сделаю грамотно всё.

При таком подходе польза обязательно должна быть smile

Добавлено @ 18:09
Цитата(toxx @  2.4.2010,  17:02 Найти цитируемый пост)
    if(capacity>k||k<0) return *this;

изменение типа k на  unsigned .. поможет избавиться от ненужной нагрузки на логику такой как проверка k<0.

Цитата(toxx @  2.4.2010,  17:02 Найти цитируемый пост)
     Vector buf=*this;
        delete[] V;

не очень удачное решение, удалять контейнер, до получения нового..
Логичнее заполнять новый, потом swap`нуть и только после этого удалять ненужное..

Добавлено через 7 минут и 49 секунд
Цитата(toxx @  2.4.2010,  17:02 Найти цитируемый пост)
 for(int i=0;i<capacity;i++)

память находящуюся между size и capacity не нужно занулять.. Это логически лишнее..

Добавлено через 11 минут и 58 секунд
Цитата(toxx @  2.4.2010,  17:02 Найти цитируемый пост)
capacit()

интерфейсные (открытые) методы желательно называть неизменным именем, в отличие от приватных членов, которые не столь придирчивы к измененному написанию.. А в общем для них желательно добавлять аффикс,  для узнаваемости, чтоб не путать с локальными переменными и передаваемыми параметрами..


Это сообщение отредактировал(а) mes - 2.4.2010, 18:09


--------------------
PM MAIL WWW   Вверх
ИванМ
Дата 2.4.2010, 18:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(toxx @  2.4.2010,  18:02 Найти цитируемый пост)
Ну я уже взялся, тем более я взялся, чтобы понять как работают классы как перекгружать и т.д. 
Да конечно я буду использовать свой вектор тока в лабах, но думаю мне пойдет на пользу если я сделаю грамотно всё.

Тогда желаю удачи в своем совершенствовании. Это правильная позиция.
PM MAIL   Вверх
mes
Дата 2.4.2010, 18:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(toxx @  2.4.2010,  17:02 Найти цитируемый пост)
    capacity=1;
    while(k>capacity)
        capacity*=2;

ну а это что еще за извращение ? увеличивать на коэффицент вместимость нужно только в том случае, если происходит переполнение при вставке, а не тогда, когда напрямую задается размер.

Добавлено через 2 минуты и 4 секунды
Цитата(toxx @  2.4.2010,  17:02 Найти цитируемый пост)
  int size(){return n;}
    int begin(){return 0;}
    int capacit(){return capacity;}
    int end(){return n;}

уже упоминал, но еще раз повторю, что тут наиболее удобными будет один из беззнаковых типов.


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


Опытный
**


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

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



mes 
1.Заменил тип(как посоветовал bsa на size_t, чтож попробуем)
Код

size_t capacity;

2.Цикл поправил
Код

for(int i=0;i<n;i++)

3. А вот насчет 
Код

 Vector buf=*this;
        delete[] V; 


не совсем понял почему, тогда придется еще дополнительно мне перегрузить operator=, чтобы уж было красиво.

4.Я не понимаю почему тогда столько книг написано по STL и довольно многие пользуются,
что не глянь тему, люди вашего уровня все переделывают на vector, iterator и пишут,что лучше его использовать(да наверно не везде)...
PM MAIL   Вверх
mes
Дата 2.4.2010, 18:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(toxx @  2.4.2010,  17:26 Найти цитируемый пост)
Я не понимаю почему тогда столько книг написано по STL и довольно многие пользуются,
что не глянь тему, люди вашего уровня все переделывают на vector, iterator и пишут,что лучше его использовать(да наверно не везде)... 

лучше чем самопально написаннный динамический массив, а также он самый простой для понимания, и лучше для тех, кто не сталкивался еще с стл,
в остальных случаях какой из конкейнеров лучше, а может даже какая их связка, зависит от решаемой задачи.
добавлю сразу, что на текущий момент стл не покрывает всех потребностей в контейнерах, но их хватает на основные жизненые случаи.
smile

Добавлено через 1 минуту и 48 секунд
Цитата(toxx @  2.4.2010,  17:26 Найти цитируемый пост)
не совсем понял почему, тогда придется еще дополнительно мне перегрузить operator=, чтобы уж было красиво.

нет, лучше добавить оператор swap , пригодится не только для текущей ситуации...  не бойтесь он очень простой в реализации smile

 


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


Опытный
**


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

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



Исправил, пока без swap'a
Код

class Vector
{
    T* V;
    size_t n;
    size_t capacity;
public:
    Vector(int=0);
    Vector(const Vector&);
    size_t size(){return n;}
    size_t begin(){return 0;}
    size_t capacit(){return capacity;}
    size_t end(){return n;}
    Vector resize(int);
    Vector& erase(int);
    void push_back(T);
    ~Vector(){delete[] V;}
    T& operator[](int i){return V[i];}
};

Код

Vector<T> Vector<T>::resize(int k)
{
    if(capacity>k) return *this;
    else 
    {
        capacity=1;
        while(k>capacity)
            capacity*=2;
        Vector buf=*this;
        delete[] V;
        n=k;
        V=new T[capacity];
        for(int i=0;i<n;i++)
        if(i<buf.size())(*this)[i]=buf[i];
            else (*this)[i]=0;
    }
    return *this;
}

и конструктор заодно
Код

Vector<T>::Vector(int k)
{
    capacity=0;
    n=k;
    V=new T[n];
}


Еще + в том, что я сразу могу проверить свой вектор на деле( я с помощью него дерево храню эн-мерное, в соседней теме)

Это сообщение отредактировал(а) toxx - 2.4.2010, 18:38
PM MAIL   Вверх
mes
Дата 2.4.2010, 18:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(toxx @  2.4.2010,  17:36 Найти цитируемый пост)
   capacity=0;
    n=k;

вместимость  не может быть меньше размера..

Добавлено @ 18:56
Цитата(toxx @  2.4.2010,  17:36 Найти цитируемый пост)
    while(k>capacity)
            capacity*=2;

у вас получается, что вместимость всегда равна степени 2ки, а суть не в этом,
а в том чтоб увеличивать текущую вместимость на определенный коэффициент.

кстати хотелось бы также отметить, что коэф. 2 не самый оптимальный, но для простоты пойдет.

Добавлено @ 18:57
В остальном нужно подождать, пока внесете изменения уже озвученные в этой теме..


Это сообщение отредактировал(а) mes - 2.4.2010, 19:01


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


Опытный
**


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

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



ИванМ,mes 
Да... идей вы мне подкинули массу, спасибо.
Как с деревом разберусь еще добавлю идею swap(mes'a).


Это сообщение отредактировал(а) toxx - 2.4.2010, 21:09
PM MAIL   Вверх
toxx
Дата 3.4.2010, 20:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



mes
А скажите пожалуйста основную идею swap?
т.е. как я понял(т.е. не понял) если менять местами векторы Х и Y это чтото типа
Код

void swap(Vector<T>& x,Vector<T>& y);

тогда применительно к чему вызывать этот метод?(я написал свой метод и объявил его другом для класса, походу это не верно...)
Код

friend void swap(Vector,Vector);

вот что получилось(если честно судя по моему забору он не верный...+ он не компилируется)
Код

void swap(Vector<T>& x,Vector<T>& y)
{
    T tmp,size_min,size_max;

    if(x.n>y.n) 
    {
        y.resize(x.n);
        size_min=y.n;
        size_max=x.n;

        for(size_t i=0;i<size_max;i++)
        {
            tmp=x[i];
            x[i]=y[i];
            y[i]=tmp;
        }

        x.resize(size_min);
    }
    else 
    {
        x.resize(y.n);
        size_min=x.n;
        size_max=y.n;

        for(size_t i=0;i<size_max;i++)
        {
            tmp=x[i];
            x[i]=y[i];
            y[i]=tmp;
        }

        y.resize(size_min);
    }
}


Еще есть идея, что он как конструктор копирования вызывается для указателя(это больше похоже на правду)
PM MAIL   Вверх
mes
Дата 3.4.2010, 20:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(toxx @  3.4.2010,  19:05 Найти цитируемый пост)
вот что получилось(если честно судя по моему забору он не верный

все гораздо проще:
Код

class Vector
{
   public:
       void swap ( Vector& rhs ) 
       {
            std::swap ( m_data,  rhs.m_data );
            std::swap ( m_size,  rhs.m_size );
       }
   private:
       T *         m_data;
       size_t      m_size;
};

smile

Это сообщение отредактировал(а) mes - 3.4.2010, 20:23


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


Опытный
**


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

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



mes
оу, до такого ябы не додумался(даже не знал о существовании такого)

Переписал resize() со swap
capacity у меня по степени двойки=)
Код

Vector<T> Vector<T>::resize(size_t k)
{
    if(capacity>k) return *this;
    else 
    {
        capacity=1;
        while(k>capacity)
            capacity*=2;

        Vector<T> buf(k);
        for(size_t i=0;i<buf.size();i++)
            if(i<n)buf[i]=(*this)[i];
                else buf[i]=0;

        delete[] V;
        n=k;
        V=new T[capacity];
        buf.swap(*this);    
    }
}

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


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


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

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



Цитата(toxx @  3.4.2010,  19:56 Найти цитируемый пост)
Переписал resize() со swap

Вы уверены ? попробуйте исправить сами без подсказки ..

Добавлено @ 21:17
Цитата(toxx @  3.4.2010,  19:56 Найти цитируемый пост)
capacity у меня по степени двойки=)

имхо логичней все таки
Код

if  (new_size>capacity) capacity = new_size * 2;




Это сообщение отредактировал(а) mes - 3.4.2010, 21:18


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


Опытный
**


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

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



mes
Интересно, я сначала подумал почему не работает...
потом откомпилировал 5 раз подряд из них 4 раза компилирует и работает, на 5й показывает ошибку доступа к памяти crtexe.c
Код

template <class T>
Vector<T> Vector<T>::resize(size_t new_size)
{
    if(capacity>new_size) return *this;
    else 
    {
        Vector buf(new_size);
        if(new_size>capacity)
            capacity=new_size*2;

        for(size_t i=0;i<n;i++)
            buf[i]=(*this)[i];

        delete[] V;
        n=new_size;
        V=new T[capacity];
        buf.swap(*this);
    }
}


Это сообщение отредактировал(а) toxx - 3.4.2010, 22:25
PM MAIL   Вверх
mes
Дата 3.4.2010, 22:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(toxx @  3.4.2010,  21:09 Найти цитируемый пост)
Vector<T> Vector<T>::resize(size_t new_size)

вообще-то resize() возвращает void 
ну а ошибки не все исправили ..


Это сообщение отредактировал(а) mes - 3.4.2010, 22:30


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


Опытный
**


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

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



Хммм... компилятор перестал выдавать ошибки crtexe.c 
я уже даже вектор нарисовал на бумажке до и после увеличения для:
Код

Vector<int> y(4);
y.resize(10);
нет ничего криминального, даже компилятор за !

Код

void Vector<T>::resize(size_t new_size)
{
    if(capacity<new_size&&n<new_size)
    {
        Vector buf(new_size);
        if(new_size>capacity)
            capacity=new_size*2;

        for(size_t i=0;i<n;i++)
            buf[i]=(*this)[i];

        delete[] V;
        n=new_size;
        V=new T[capacity];
        buf.swap(*this);
    }
}

PM MAIL   Вверх
mes
Дата 3.4.2010, 23:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(toxx @  3.4.2010,  21:43 Найти цитируемый пост)
нет ничего криминального, даже компилятор за !

компилятор проверяет корректность , а не логичность.. 
smile

Цитата(toxx @  3.4.2010,  21:43 Найти цитируемый пост)
  if(capacity<new_size&&n<new_size) // не кажется что у обоих условий должна быть своя логика обработки ?
    {
        Vector buf(new_size); // а в конструкторе вызывается resize ? не боитесь  рекурсии ?

        if(new_size>capacity) 
            capacity=new_size*2; // а зачем изменять переменную текущего вектора ?

        for(size_t i=0;i<n;i++)
            buf[i]=(*this)[i];  // ну копирование пойдет.. 

        delete[] V;        // а тут зачем удаление ?
        n=new_size;   
        V=new T[capacity]; // и создаете новый ? может вместо этих двух операций достаточно swapa ?
        buf.swap(*this); 
    }




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


Опытный
**


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

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



Код

template <class T>
void Vector<T>::resize(size_t new_size)
{
    if(capacity<new_size&&n<new_size)
    {
        Vector buf(new_size);
        if(new_size>capacity)
            capacity=new_size*2;

        for(size_t i=0;i<n;i++)
            buf[i]=(*this)[i];

        buf.swap(*this);
    }
}

Как сложно делать вещи логичными оказывается....

1.тут я делаю чтобы ёмкость у изменяемого вектора была new_size*2;
Код

if(new_size>capacity)
    capacity=new_size*2;

2.Так вродебы это не прямая рекурсия, а косвенная...какие слова я знаю ухх
3.Пока я был уверен что я прав в предыдущем посте... набросал функцию push_back(уже боюсь что тут что-то я не логично сделал, но я старался быть таковым)
Код

void Vector<T> ::push_back(T k)
{
    Vector buf=*this;
    n++;
    delete []V;
    V=new T[n];
    for(size_t i=0;i<n;i++)
    if(i==(n-1))(*this)[i]=k;
        else (*this)[i]=buf[i];
}

4.Мне нужна будет сортировка массива, вношу быструю сортировку с разделением
Код

void Vector<T>::sort(size_t First,size_t Last)
{
    size_t i=First,j=Last;
    T mid,x;
    mid=(First+Last)/2;
    x=V[mid];
    do
    {
        while(V[i]>x)
        {
            i++;
            while(x>V[j])
            {
                j++;
                if(i<=j)
                {
                    T tmp;
                    tmp=V[i];
                    V[i]=V[j];
                    V[j]=tmp;
                    i++;
                    j--;
                }
            }
        }
    }
    while(i>j);

    if(First<j) sort(First,j);
    if(i<Last) sort(i,Last);
}


Это сообщение отредактировал(а) toxx - 3.4.2010, 23:51
PM MAIL   Вверх
mes
Дата 3.4.2010, 23:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(toxx @  3.4.2010,  22:50 Найти цитируемый пост)
набросал функцию push_back(

что за удаление/создание внутри push_backa?  smile

Добавлено через 7 минут и 40 секунд
Цитата(toxx @  3.4.2010,  22:50 Найти цитируемый пост)
1.тут я делаю чтобы ёмкость у изменяемого вектора была new_size*2;

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

Цитата(toxx @  3.4.2010,  22:50 Найти цитируемый пост)
2.Так вродебы это не прямая рекурсия, а косвенная...какие слова я знаю ухх

ну а что меняет ? 

Цитата(toxx @  3.4.2010,  22:50 Найти цитируемый пост)
4.Мне нужна будет сортировка массива, вношу быструю сортировку с разделением

сортировка не является методом вектора.. Она должна быть внешней  функцией.


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


Опытный
**


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

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



Цитата

что за удаление/создание внутри push_backa?

Код

void Vector<T> ::push_back(T new_item)
{
    if(capacity<=n)
    {
        Vector buf=*this;
        n++;
        buf.resize(n);
        buf[n-1]=new_item;
        buf.swap(*this);
    }
}

блин, вот и блин...
А рекурсия не идет в методе?или я совсем чтото затупил...

Это сообщение отредактировал(а) toxx - 4.4.2010, 00:12
PM MAIL   Вверх
mes
Дата 4.4.2010, 00:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(toxx @  3.4.2010,  23:07 Найти цитируемый пост)
блин, вот и блин...


прежде всего будьте проще :

Код

void vector::push_back (T const& new_item)
{
      if ( size() = capacity() ) reserve ( capacity() * 2 );

      (*this)[m_size++] = new_item;
}

smile

Это сообщение отредактировал(а) mes - 4.4.2010, 00:25


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


Опытный
**


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

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



Код

void Vector<T>::resize(size_t new_size)
{
    if(capacity<new_size&&n<new_size)
    {
        Vector buf(new_size);
        buf.capacity=new_size*2;

        for(size_t i=0;i<n;i++)
            buf[i]=(*this)[i];

        buf.swap(*this);
    }
}


Про сортировку понял...

Добавлено @ 00:30
у меня  reserve нету =(

ну у меня тоже красиво выгрядит push_back...
я себя прям чувствую совсем бесполезным на фоне вашей логики=(
А можно хотябы пузырьковую как метод добавить?или одельно только совсем?

Это сообщение отредактировал(а) toxx - 4.4.2010, 00:32
PM MAIL   Вверх
mes
Дата 4.4.2010, 00:32 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Код

void vector::resize (size_t new_size)
{
    if ( new_size <= size() ) return;

    if ( new_size > capacity() )
            reserve ( capacity() * 2 );
         
    while  ( m_size != new_size )
          (*this)[m_size++] = T();
}


Добавлено @ 00:33
Цитата(toxx @  3.4.2010,  23:26 Найти цитируемый пост)
у меня  reserve нету =(

ну так кто мешает добавить ?

Добавлено @ 00:39
Код

void Vector::reserve (size_t new_cap)
{
     if (new_cap <= capacity() ) return;
      
     Vector tmp;

     tmp.m_data = new T[new_cap];
     tmp.m_capacity = new_cap;     
     tmp.m_size = m_size;
  
     for (size_t i=0; i<m_size; ++i)
        (*tmp)[i] = (*this)[i];

     tmp.swap (*this);
     
}


Добавлено @ 00:40
Цитата(toxx @  3.4.2010,  23:26 Найти цитируемый пост)
на фоне вашей логики

к сожалению не моей.. я ее когда-то подсмотрел )

Добавлено @ 00:41
Цитата(toxx @  3.4.2010,  23:26 Найти цитируемый пост)
А можно хотябы пузырьковую как метод добавить?или одельно только совсем?

зачем его как метод добавлять ?

Добавлено @ 00:42
P.S. код писал здесь и не проверял..к тому же сейчас ночь - могут быть ошибки.. я просто передавал суть..  так что внимательней  smile


Это сообщение отредактировал(а) mes - 4.4.2010, 10:21


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


Опытный
**


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

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



Добавлено @ 00:50
mes
Охх спасибо за эти советы вроде бы разобрался в том что вы скинули...
код вродебы простой, но меня не посещают пока такие строки =(

...Пока разбирался и искал что такое reserve() вы ушли =)

Это сообщение отредактировал(а) toxx - 4.4.2010, 01:36
PM MAIL   Вверх
mes
Дата 4.4.2010, 10:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(toxx @  3.4.2010,  23:42 Найти цитируемый пост)
и искал что такое reserve()

reserve() отвечает за capacity
resize()    отвечает за size

на будущее, если захотите вектор довести до ума, то еще неплохо бы посмотреть, на функции
uninitialized_copy и uninitialized_fill
http://cplusplus.com/reference/std/memory/...itialized_copy/
http://cplusplus.com/reference/std/memory/...itialized_fill/

и разобраться что представляет из себя аллокатор
http://cplusplus.com/reference/std/memory/allocator/

Это сообщение отредактировал(а) mes - 4.4.2010, 10:30


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


Опытный
**


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

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



Цитата(mes @ 4.4.2010,  10:30)
Цитата(toxx @  3.4.2010,  23:42 Найти цитируемый пост)
и искал что такое reserve()

reserve() отвечает за capacity
resize()    отвечает за size

на будущее, если захотите вектор довести до ума, то еще неплохо бы посмотреть, на функции
uninitialized_copy и uninitialized_fill
http://cplusplus.com/reference/std/memory/...itialized_copy/
http://cplusplus.com/reference/std/memory/...itialized_fill/

и разобраться что представляет из себя аллокатор
http://cplusplus.com/reference/std/memory/allocator/

Да я всё нашел smile 
И еще у вас в коде я увидел некоторые, я бы сказал для себя фишки например
1.
Код

while  ( m_size != new_size )
       (*this)[m_size++] = T();

как я понимаю это отсюда
Код

template <class T>

Но в чем отличие?Для себя я уяснил что это тоже самое, как для любого типа занулить?
только почему не (*this)[m_size++] = T, а именно Т()?
2. в этойже строчке (*this)[m_size++]  m_size++  увеличивается прям в []? вродебы как пост инкремент...
Сам я боюсь использовать такую конструкцию, боюсь что неверный результат будет стараюсь делать это за квадртаными скобками.
Еще нашел, что приоритет у [] выше чем у m_size++, получается что выполняется сначала в цикле для m_size а в следующем цикле для увеличенного m_size на 1.
PM MAIL   Вверх
mes
Дата 4.4.2010, 12:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(toxx @  4.4.2010,  10:54 Найти цитируемый пост)
= T, а именно Т()?

ну так а в чем отличие к примеру между int и int() знаете ? в одном случае имя типа, а в другом создание объекта.

Цитата(toxx @  4.4.2010,  10:54 Найти цитируемый пост)
Сам я боюсь использовать такую конструкцию, боюсь что неверный результат будет стараюсь делать это за квадртаными скобками.

"не уверен не обгоняй" ©  - пока делайте за скобками, как прочувствуете  эту операцию, перестанете бояться smile

Цитата(toxx @  4.4.2010,  10:54 Найти цитируемый пост)
Еще нашел, что приоритет у [] выше чем у m_size++,

приоретет сказывается на разбор команды,  но не на ее выполнение.
Особенность постинкремента (а также постдекремента) в том, что результатом будет значение до его изменения..
smile





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


Опытный
**


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

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



Проверил все эти новшества на своём дереве, что-то перемудрили походу с функциями
resize() reserve()
mes 
p.s. скажите, пожалуйста только за что отвечает эта ошибка?
Ошибка
PM MAIL   Вверх
mes
Дата 4.4.2010, 18:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(toxx @  4.4.2010,  17:48 Найти цитируемый пост)
скажите, пожалуйста только за что отвечает эта ошибка?

она говорит о том, что выходите за  границы памяти.. т.е пишите не куда положено... smile


Цитата(toxx @  4.4.2010,  17:48 Найти цитируемый пост)
что-то перемудрили походу с функциями
resize() reserve()


ну показывайте код вектора, посмотрим чего там перемудренно 
smile


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


Опытный
**


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

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



mes
Только не говорите пожалуйста, я сам попробую

Код

using namespace std;
template <class T>
class Vector
{
    T* V;
    size_t n;
    size_t capacity_m;
public:
    Vector(size_t=0);
    Vector(const Vector&);

    size_t size(){return n;}
    void reserve(size_t );
    size_t begin(){return 0;}
    size_t end(){return n;}
    size_t capacity(){return capacity_m;}

    Vector& erase(size_t);
    void swap (Vector& );
    void push_back(T);
    void resize(size_t);
    
    ~Vector(){delete V;}

    T& operator[](size_t);
};
template <class T>
void Vector<T>::swap(Vector& Vect)
{
    std::swap (V,  Vect.V);
    std::swap (n,  Vect.n);
    std::swap (capacity_m,  Vect.capacity_m);
}
template <class T>
Vector<T>::Vector(const Vector& Vect)
{
    n=Vect.n;
    capacity_m=Vect.capacity_m;
    V=new T[capacity_m];
    for(size_t i=0;i<n;i++)
        (*this)[i]=Vect.V[i];
}
template <class T>
T& Vector<T>::operator [](size_t i)
{
    if(i<n) return V[i]; 
    throw out_of_range("vector index");
}
template <class T>
Vector<T>::Vector(size_t new_size)
{
    n=new_size;
    capacity_m=new_size;
    V=new T[new_size];
    for(size_t i=0;i<new_size;i++)
        (*this)[i]=T();
}
template <class T>
Vector<T>& Vector<T> ::erase(size_t k)
{
    if(k>=n)throw out_of_range("vector index");
    Vector buf=*this;
    n--;
    delete[] V;
    V=new T[n];
    for(size_t i=0;i<n;i++)
    if(i!=k)(*this)[i]=buf[i];
    else 
    {
        (*this)[i]=buf[i+1];
        k++;
    }
}
template <class T>
void Vector<T> ::push_back(T new_item)
{
    if ( size() == capacity() ) reserve ( capacity() * 2 );
      (*this)[n++] = new_item;
}
template <class T>
void Vector<T>::resize(size_t new_size)
{
    if ( new_size <= size() ) return;
    if ( new_size > capacity() )
            reserve ( capacity() * 2 );
         
    while  ( n != new_size )
          (*this)[n++] = T();
}

template <class T>
void Vector<T>::reserve (size_t new_cap)
{
     if (new_cap <= capacity() ) return;
      
     Vector buf;
     buf.V = new T[new_cap];
     buf.capacity_m = new_cap;     
     buf.n = n;
  
     for (size_t i=0; i<n; ++i)
        buf[i] = (*this)[i];
     buf.swap (*this);   
}

PM MAIL   Вверх
mes
Дата 4.4.2010, 19:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(toxx @  4.4.2010,  18:06 Найти цитируемый пост)
Только не говорите пожалуйста, я сам попробую

ну я только слегка подскажу..  smile

функция erase не вызывает переаллокации и никак не влияет на вместимость, она только удаляет (затирает) ненужный элемент.



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


Опытный
**


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

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



А я нашел...)))
Нужно добавить:
Код

delete[] V;
V=new T[new_size];  

Память массива не увеличивалась, но цикл шел и обнулял до новой помяти=)
Код

void Vector<T>::resize(size_t new_size)
{
    if ( new_size <= size() ) return;
    if ( new_size > capacity() )
            reserve ( capacity() * 2 );
    delete[] V;
    V=new T[new_size];  
    while  ( n != new_size )
          (*this)[n++] = T();
}


Добавлено через 4 минуты и 13 секунд
или не нашел...

Добавлено через 7 минут и 20 секунд
А если убрать в erase()
Код

delete[] V;
V=new T[n];

То тоже работает, да верно этот метод я не трогал с последних советов ИванМ
А щас нужно измить слегка с учетом новых методов.
PM MAIL   Вверх
mes
Дата 4.4.2010, 19:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(toxx @  4.4.2010,  18:23 Найти цитируемый пост)
Нужно добавить:

а вызов reserve() на что ?


Цитата(toxx @  4.4.2010,  18:23 Найти цитируемый пост)
А щас нужно измить слегка с учетом новых методов. 

вообще то новые методы на функционал erase не влияют ..



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


Опытный
**


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

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



mes
Тогда странно, если не влияют я при удалении вершин использую только erase() 
Код

void Tree::remove()
{
    for(size_t i=0;i<Trees.size();)
    if (Trees[i]->Trees.size()%2!=0)
    {
        delete Trees[i];
        Trees.erase(i);    
    }
    else 
    {
        Trees[i]->remove();
        ++i;
    }
}

Еще также использую resize() при создании дерева.
Да, я понимаю что reverse() вместо этих строк
Код

delete[] V;
V=new T[new_size];  

Но если они присутствуют всё работает =)
PM MAIL   Вверх
mes
Дата 4.4.2010, 21:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(toxx @  4.4.2010,  18:44 Найти цитируемый пост)
Но если они присутствуют всё работает =) 

ну так значит надо внимательно просмотреть логику .. Насколько я заметил Вы использовали мой код без изменений, а я предупреждал , что в нем могут быть ошибки.

Вот сейчас просмотрел и бросилось в глаза

Цитата(toxx @  4.4.2010,  18:23 Найти цитируемый пост)
    if ( new_size > capacity() )
            reserve ( capacity() * 2 );


а должно быть, и об этом уже писалось :
Код

if ( new_size > capacity() )
   reserve ( new_size *2);

хотя нужность коэффициента при resize сомнительна, и мне кажется, что он необходим при "шаговом" заполнении, т.е. при push_back.



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


Опытный
**


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

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



mes
Да, без изменений признаю.Но как говорится доверяй, но проверяй.Я предварительно проверил на различных массивах и с использованием методов разных.
Всё работало.Так бы эта ошибка и была, только сегодня я решил опробовать обновлённый вектор на моей лабораторной(ну вот стукнуло).
Там совсем другая структура ( дерево n- мерное).
И ошибка памяти... Сначала посмотрел, нашел где ошибка ...  ну приблизительно.
Менял несколько раз этот resize(), потом только решил обратиться.Так, что чуть что, я не пишу пост просто так...

А насчет метода reserve() я как раз вчера нашел(как раз, то что вы пишите), что он эффективен только если мы добавляем элементы методом push_back.
Выделили приблизительно сколько нам нужно памяти и добавляем.
PM MAIL   Вверх
mes
Дата 4.4.2010, 22:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(toxx @  4.4.2010,  21:20 Найти цитируемый пост)
А насчет метода reserve() я как раз вчера нашел(как раз, то что вы пишите), что он эффективен только если мы добавляем элементы методом push_back.

это в случае предварительного вызова reserve () "из вне".. а я говорил о случаях вызова reserve самим вектором при нехватки памяти..
smile


Цитата(toxx @  4.4.2010,  21:20 Найти цитируемый пост)
Менял несколько раз этот resize(), потом только решил обратиться.

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

Добавлено @ 22:31
кстати.. Внутри вектора Вы используете (*this)[] хотя в большинстве случаев логичней использовать блок данных напрямую, то есть V[].
ну а также хотелось бы показать на отсутствие вызова деструктора у объектов контейнера, что в принципе на текущем этапе не серьезно..

Добавлено @ 22:35
Цитата(toxx @  4.4.2010,  21:20 Найти цитируемый пост)
Да, без изменений признаю

ну тогда ловите и стирание :
Код

void Vector<T> ::erase(size_t idx)
{
    if (idx >= m_size) throw out_of_range("vector index");

    m_size--;

    for (size_t i=idx; i<m_size; ++i)   V[i] = V[i+1];
}


Это сообщение отредактировал(а) mes - 4.4.2010, 22:36


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


Опытный
**


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

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



mes
Да, работает Спасибо=)

Я также тестировал вчера предложенные вами функции smile (только у меня это всё сделано cout<<.... в main'e все параметры выводит)
Там ничего не было...Другое дело сегодня заменил старые функции при работе с деревьями и понеслось как говориться =)

Еще я параллельно читал Страуструпа у него есть в книге "Язык программирования С++ спец. изд."
Очень интересная глава "Безопасность исключений и стандартная библиотека"
Так вот в ней я подсмотрел перегрузку оператора []
Код

T& Vector<T>::operator [](size_t i)
{
    if(i<n) return V[i]; 
    throw out_of_range("vector index");
}


Также прочитал (гарантии с контейнерами) и обратил внимание, что у вектора какието слабые гарантии либо прочерки вообще стоят
Там в виде таблицы для vector deque list map
PM MAIL   Вверх
mes
Дата 4.4.2010, 23:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(toxx @  4.4.2010,  21:44 Найти цитируемый пост)
подсмотрел перегрузку оператора []

у стандартного вектора доступ посредством [] не контролирует границ, а для контролируемого доступа есть функция at().



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


Опытный
**


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

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



mes
Вот откуда вы берёте информацию?
Вы так уверенно говорите как будто у вас перед глазами эта библиотека smile (просто поражает в положительном смысле)
Или же вы уже имели дело с её написанием?

Ведь действительно это функция at(size_t i)...

Это сообщение отредактировал(а) toxx - 4.4.2010, 23:15
PM MAIL   Вверх
mes
Дата 5.4.2010, 10:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(toxx @  4.4.2010,  22:14 Найти цитируемый пост)
Вот откуда вы берёте информацию?

при столкновении с вопросами по стл в первую очередь лезу в документацию на сайте cplusplus.com

Цитата(toxx @  4.4.2010,  22:14 Найти цитируемый пост)
как будто у вас перед глазами эта библиотека

ну вектор это самое простое из стл, его фактически все знают.

Цитата(toxx @  4.4.2010,  22:14 Найти цитируемый пост)
Или же вы уже имели дело с её написанием?

так же как и Вы проходил написание собственного векторного велосипеда плюс имеется небольшой опыт работы с с стл.
smile

Это сообщение отредактировал(а) mes - 5.4.2010, 10:25


--------------------
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

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

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

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

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


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

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


 




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


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

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