ФлеймФорумПрограммирование

Создан стек (4 стр)

Страницы: 13 4 5 612 Следующая »
#45
11:10, 6 апр 2010

"Вообще-то, действительное понимание областей видимости объектов и знание правил автоматических вызовов конструкторов и деструкторов, позволяют не горевать особо о мусоросборщиках а-ля Жаба, экономят (порой весьма значительно) доступную память и увеличивают (тоже, зачастую, значительно) быстродействие программы. Правда, обладают этими действительными знанием и пониманием лишь около 5% кодеров на Це-плюсь-плюсе. Остальные 95 - ругаются с компилятором и говорят, что С++ «не работает»." (c) место_чьё_имя_нельзя_упоминать

#46
18:14, 6 апр 2010

Рад представить исправленную версию.
Фактически переписанную заново.
Использовал список пулов. Такой подход позволил избавиться от бестолкового копирования, частого выделения памяти, а так-же теперь стек может сам уменьшаться в размере не забывая на всякий случай оставить один пул про запас.
Стек был протестирован с intами и std::string. Ошибок не найдено.
Офк пару вопросов:
Правильно ли реализован метод pop с точки зрения возвращаемого значения?
Как превратить грязный сишный хак в красивый С++ код? Это из метода Resize? смысл в том, что указатель data должен указывать сразу за собой.

/*----------------------------------------------------------------------------*/
/*                                 6y6yka Engine                              */
/*----------------------------------------------------------------------------*/
#ifndef _B_STACK_H_
#define _B_STACK_H_
/*----------------------------------------------------------------------------*/
#include <cstdlib>
#include <cassert>
/*----------------------------------------------------------------------------*/
/* класс bStack                                                               */
/* описание:                                                                  */
/*     реализация структуры типа стек                                         */
/* методы:                                                                    */
/*     Push    помещает данные в стек                                         */
/*     Pop     удаляет верхний элемент                                        */
/*     Top     возвращает ссылку на верхний элемент                           */
/*     Length  возвращает количество элементов                                */
/*     Size    возвращает объем занимаемой памяти                             */
/*     Resize  резервирует память для будущих действий                        */
/*----------------------------------------------------------------------------*/
template <typename bStackType>
class bStack
{
public:
  bStack();
  ~bStack();

  void Push(const bStackType &item);
  void Pop();
  bStackType &Top() const;

  int Length()      const;
  int Size()        const;
  int Resize(unsigned int new_size);
private:
  struct data_pool;

  data_pool *pool; // список пулов
  data_pool *old_pool;
  int allocated;   // всего выделено памяти(в итемах)
  int length;      // количество использующихся итемов

  static const int defsize = 10;

  bStack(const bStack &);
  bStack &operator =(const bStack &);
};
/*----------------------------------------------------------------------------*/
/* bStack<bStackType>::bStack                                                 */
/*----------------------------------------------------------------------------*/
template <typename bStackType>
inline bStack<bStackType>::bStack()
{
  pool      = old_pool = 0;
  allocated = length   = 0;
}
/*----------------------------------------------------------------------------*/
/* bStack<bStackType>::~bStack                                                */
/*----------------------------------------------------------------------------*/
template <typename bStackType>
inline bStack<bStackType>::~bStack()
{
  free(old_pool);

  if(pool)
    pool->size -= allocated - length; // вычитаем число пустых ячеек

  while(pool)
  {
    for(int i = 0; i < pool->size; i++)
      pool->data[i].~bStackType();

    old_pool = pool;
    pool = pool->next;
    free(old_pool);
  }
}
/*----------------------------------------------------------------------------*/
/* bStack<bStackType>::Push                                                   */
/* описание:                                                                  */
/*     помещает новый элемент в стек                                          */
/* аргументы:                                                                 */
/*     item    ссылка на новый элемент                                        */
/*----------------------------------------------------------------------------*/
template <typename bStackType>
inline void bStack<bStackType>::Push(const bStackType &item)
{
  if(allocated == length) // если стек полон или совсем пуст
  {
    if(!old_pool)
      Resize(allocated * 2);

    old_pool->next = pool;
    pool = old_pool;
    old_pool = 0;
    allocated += pool->size;
  }

  new(&pool->data[pool->size - (allocated - length++)]) bStackType(item);
}
/*----------------------------------------------------------------------------*/
/* bStack<bStackType>::Pop                                                    */
/* описание:                                                                  */
/*     удаляет элемент с верхушки стека                                       */
/*----------------------------------------------------------------------------*/
template <typename bStackType>
inline void bStack<bStackType>::Pop()
{
  int i = pool->size - (allocated - --length);
  assert(!(i < 0));             // недопущение противоправных действий.

  pool->data[i].~bStackType();

  if(!i && pool->next)
  {
    if(old_pool)
      free(old_pool);

    allocated -= pool->size;
    old_pool = pool;
    pool = pool->next;
  }
}
/*----------------------------------------------------------------------------*/
/* bStack<bStackType>::Top                                                    */
/* описание:                                                                  */
/*     возвращает ссылку на верхний элемент                                   */
/*----------------------------------------------------------------------------*/
template <typename bStackType>
inline bStackType &bStack<bStackType>::Top() const
{
  return pool->data[pool->size - (allocated - (length - 1))];
}
/*----------------------------------------------------------------------------*/
/* bStack<bStackType>::Leangth                                                */
/* описание:                                                                  */
/*     возвращает количество элементов в стеке                                */
/*----------------------------------------------------------------------------*/
template <typename bStackType>
inline int bStack<bStackType>::Length() const
{
  return length;
}
/*----------------------------------------------------------------------------*/
/* bStack<bStackType>::Size                                                   */
/* описание:                                                                  */
/*     возвращает максимальное количество элементов.                          */
/*----------------------------------------------------------------------------*/
template <typename bStackType>
inline int bStack<bStackType>::Size() const
{
  return allocated;
}
/*----------------------------------------------------------------------------*/
/* bStack<bStackType>::Resize                                                 */
/* описание:                                                                  */
/*     увеличивает максимально колличество элементов                          */
/* аргументы:                                                                 */
/*     new_size    новый размер в итемах                                      */
/* возвращает:                                                                */
/*     полный размер стека в итемах                                           */
/*----------------------------------------------------------------------------*/
template <typename bStackType>
inline int bStack<bStackType>::Resize(unsigned int new_size)
{
  free(old_pool);

  old_pool = static_cast<data_pool *>(
           malloc(sizeof(data_pool) + sizeof(bStackType) * 
               (new_size ? new_size : new_size = defsize)));
  old_pool->size = new_size;
  old_pool->data = reinterpret_cast<bStackType *>(
                 reinterpret_cast<size_t *>(&old_pool->data) + 1);

  return allocated;
}
/*----------------------------------------------------------------------------*/
/* bStack<bStackType>::data_pool                                              */
/* описание:                                                                  */
/*     структура для организации списка                                       */
/*----------------------------------------------------------------------------*/
template <typename bStackType>
struct bStack<bStackType>::data_pool
{
  int size;         // размер куска в итемах
  data_pool *next;  // указатель на предыдущий пулл
  bStackType *data; // указатель на начало данных
};
/*----------------------------------------------------------------------------*/
#endif /* _B_STACK_H_ */
#47
18:29, 6 апр 2010

Pokimon
не пойму что такое OldPool...

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

или у тебя односвязный список пулов по N элементов??
если так, то реализуй простейший стек на N элементов, так как я показал, потом реализуй список, а потом реализуй свой мегастек через список стеков... в итоге у тебя будет 3 разных контейнера, по цене 2,5...

#48
18:41, 6 апр 2010

Pushkoff
> не пойму что такое OldPool...
Здесь хранится освободившаяся память для будущего использования.

Pushkoff
> для описания стека тебе должно хватить 3 указателей
Ну да...
Если бы все было так просто, тема закончилась уже на 1 странице.
Мы живем в век обобщенного программирования.
Поэтому стек должен уметь сам увеличивать свой размер и уменьшать и хранить ЛЮБЫЕ данные.
Мне кажется, что организация стека в виде непрерывного массива ущербна.
Потому, что приходится копировать данные при resize(). А данные они разные. некоторые копируются довольно сложно.

Pushkoff
> или у тебя односвязный список пулов по N элементов??
Односвязный список пулов в каждом по разному элементов и 1 пул сохраняется на всякий случай.

#49
19:06, 6 апр 2010

Pokimon
> bStackType Pop();

Саттер негодуэ по поводу "гарантий бессбойности при исключениях".

#50
19:20, 6 апр 2010

du_hast
> Саттер негодуэ по поводу "гарантий бессбойности при исключениях".
Не понял?
Какие еще тут исключения?
bad_alloc я не рассматриваю. это фантастика.
И вообще зачем писать загадками?
Просто расскажите как сделать идеальный Pop

#51
19:25, 6 апр 2010

Pokimon

> allocated - --length
OH SHI--

#52
19:56, 6 апр 2010

Мне кажется, стек накроется, если new_size в Resize будет < 0...

#53
20:14, 6 апр 2010

Pushkoff
> для описания стека тебе должно хватить 3 указателей..
> - начало
> - текущий элемент
> - конец
Для описания стека достаточно одного указателя

#54
20:24, 6 апр 2010

Pokimon
> Рад представить исправленную версию.
предидущая была лучше, честно
http://pastebin.com/E96bsVJk

#55
20:38, 6 апр 2010

AndryBlack
> Для описания стека достаточно одного указателя
тогда это будет односвязный список...

#56
20:42, 6 апр 2010

AndryBlack
> http://pastebin.com/E96bsVJk
Вы намекаете, что по этой ссылке реализация стека достойная внимания?
Да это поделие даже не компилируется(по крайней мере студией).
И вообще не конкурент моему стеку ни по скорости ни по простоте использования.

AndryBlack
> предидущая была лучше, честно
Предыдущая была с фатальными ошибками. Не заметит их только слепой.

#57
20:46, 6 апр 2010

Voltt
> Мне кажется, стек накроется, если new_size в Resize будет < 0...
щас добавлю asseric
дельный совет.

правка: добавил assert
исправил баг с удалением в деструкторе.
Пошел тестить на скорость.

правка: пока тестил обнаружил, что у std::stack функция Pop просто удаляет элемент и ничего не возвращает.
Сделаю так-же.

#58
21:32, 6 апр 2010

Zefick
> в конструкторе сразу выделил память под default_size элементов не дожидаясь вызова Push и сделал бы default_size равным не 1, а сразу, например, 10.
Плохая идея. Отвратительная.

#59
21:44, 6 апр 2010

Написал простой тестик.
работа с миллионом строк типа "Medved"
std::stack vs bstack
std::stack :  0.44
bstack      :  0.24
Тоесть мой стек, моя задумка, мой способ мышления обыгрывает в 2 раза реализацию из stl
Вобщем я счастлив, поэтому и пишу на форум.

#include <string>
#include <iostream>
#include <stack>
#include <windows.h>
#include "b_stack.h"

int main()
{
  bStack<std::string> bstack;
  std::stack<std::string> sstack;
  LARGE_INTEGER b_1, b_2, s_1, s_2, freq;
  double br, sr;

  std::string test = "Medved";
  std::string result;

  QueryPerformanceFrequency(&freq);

  QueryPerformanceCounter(&b_1);

  for(int i = 0; i < 1000000; i++)
    bstack.Push(test);
  for(int i = 0; i < 1000000; i++)
  {
    result = bstack.Top();
    bstack.Pop();
  }
  for(int i = 0; i < 1000000; i++)
  {
    bstack.Push(test);
    result = bstack.Top();
    bstack.Pop();
  }
  QueryPerformanceCounter(&b_2);
  br = (double)(b_2.QuadPart - b_1.QuadPart)/freq.QuadPart;

  QueryPerformanceCounter(&s_1);
  for(int i = 0; i < 1000000; i++)
    sstack.push(test);
  for(int i = 0; i < 1000000; i++)
  {
    result = sstack.top();
    sstack.pop();
  }
  for(int i = 0; i < 1000000; i++)
  {
    sstack.push(test);
    result = sstack.top();
    sstack.pop();
  }
  QueryPerformanceCounter(&s_2);
  sr = (double)(s_2.QuadPart - s_1.QuadPart)/freq.QuadPart;

  std::cout << "bstack result: " << br << std::endl;
  std::cout << "std::stack result: " << sr << std::endl;
  system("pause");

  return 0;
}
Страницы: 13 4 5 612 Следующая »
ФлеймФорумПрограммирование

Тема в архиве.