Форум программистов, компьютерный форум CyberForum.ru

Шаблон класса двусвязный список - C++

Восстановить пароль Регистрация
Другие темы раздела
C++ Перевести с DELPHI в С++ http://www.cyberforum.ru/cpp-beginners/thread318359.html
Кто-нибудь сможет помочь переписать код с delphi на с++? И вообще возможно ли это?
C++ Нормальное Распределение чисел есть программа. вычисляет нормально распределенные два числа методом Бокса — Мюллера, не могу сделать что выводила случайную последовательность а не два числа. помогите плиз! #include <math.h> typedef unsigned long long u64; typedef long long s64; typedef double d64; typedef struct { u64 rec_count; u64 start; http://www.cyberforum.ru/cpp-beginners/thread318357.html
C++ Как изучать С++ ?
Уважаемые участники форума, я тут на досуге - невзначай решил научиться азам С++. Нашел кучу учебников сижу типа читаю. Столкнулся с проблемой - масса ненужной информации и нет систематизации материала. Обычно начинают вешать всякую лапшу на уши о том как вначале ничего не было. потом создали компьютер, юзера, админа, Windows итд итп, а потом бац и сложный материал. Может ли мне кто...
C++ Нахождение кратчайшего пути в неорентированном графе от заданой вершины к заданной
Добрый день. Вот решаю задачку о кратчайщем расстояние между двумя верщинами в неорентированном связном графе без циклов. Заданны такие параметры. (Помещаю их в файл text2.txt) 6 -- количество вершин N 1 2 7 -- Начало, конец, длина 2 3 3 2 4 6 4 5 3 5 6 1 4 -- количество пар вершин M для которых нужно узнать короткое растояние
C++ Массив http://www.cyberforum.ru/cpp-beginners/thread318283.html
Помогите разобраться. Только начал читать про указатели и решил написать простенькую программку :) Она считает кол-во прописных букв и записывает эти буквы в массив. Насчет счетчика всё ясно, но вот как записывать буквы в массив не разобрался. GNU nano 2.2.6 Файл: p209E12.cpp #include <cctype> #include <iostream> using namespace std; main() {
C++ исправить код программы #include<iostream.h> #include<conio.h> #include<stdlib.h> #include<string.h> #include<iomanip.h> float f( float, float, float, float); float pr_chet( float *mas, int k); float sum_f( float *mas,int k); void Vivod_mas(float a,int k); подробнее

Показать сообщение отдельно
lemegeton
 Аватар для lemegeton
2908 / 1337 / 133
Регистрация: 29.11.2010
Сообщений: 2,720
12.06.2011, 21:22     Шаблон класса двусвязный список
Давайте попробую разжевать маленько.
Все на самом деле очень просто.
Значит так. Давайте сделаем так, что начало и конец списка хранит элемент класса List под названием base. base.next указывает на первый элемент списка, base.prev на последний. При этом количество кода на удаление и добавление элементов сокращается до одной строки.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <iostream>
 
// базовый класс элемента связного списка
// не содержит данных, содержит часть логики
struct NodeBase {
  NodeBase *prev; // указатель на предыдущий элемент связного списка
  NodeBase *next; // указатель на следующий элемент связного списка
  // при создании объекта класса конструктор по-умолчанию
  // назначает следующий и предыдущий элемент указывать на себя 
  NodeBase() : prev(this), next(this) {}
  // при создании с таким констуктором, элемент добавляет сам себя
  // в связный список, представляя себя предыдущему и следующему элементу
  NodeBase(NodeBase *prev_, NodeBase *next_)
    : prev(prev_), next(next_) { // назначаются предыдущий и следующий элементы
    // у предыдущего элемента следующим элементом назначается данный элемент
    // и у следующего элемента предыдущим элементом назначается данный элемент
    prev->next = next->prev = this;
  }
  // деструктор. при удалении элемента связного списка, 
  // элемент убирает сам себя из списка
  virtual ~NodeBase() {
    prev->next = next;
    next->prev = prev;
  }
};
 
// элемент связного списка, уже содержащий данные.
template <typename ValueType>
struct Node: public NodeBase{
  ValueType value; // то значение, которое хранит класс
  // конструктор подставляет значения и вызывает конструтор предка
  Node(NodeBase *prev_, NodeBase *next_, ValueType value)
    : NodeBase(prev_, next_), value(value) {}
};
 
// собственно, шаблон двусвязного списка
// смотрите, как мало собственно кода, если убрать комментарии
template <typename ValueType>
class List {
 public:
  // конструктору по-умолчанию делать в принципе нечего, он должен быть объявлен
  List() : base() {};
  // деструктор удаляет список функцией Clear
  ~List() {
    Clear();
  }
  // функция проверяет, пустой ли список
  bool Empty() {
    // список пустой, если базовый элемент указывает сам на себя
    return ((base.next == &base) && (base.prev == &base));
  }
  void Clear() {
    // пока список не пуст
    while (!Empty())
      // удаляется первый элемент
      // работу по удалению из списка сделает деструктор класса элемента
      delete base.next;
  }
  // добавление элемента в конец списка
  void PushBack(const ValueType &value) {
    // просто создается новый элемент списка,
    // всё остальное сделает конструктор класса NodeBase
    new Node<ValueType>(base.prev, &base, value);
  }
  // удаление последнего элемента
  void PopBack() {
    // удаляется элемент связного списка 
    // (в данном случае последний, но в принципе, сработает с любым)
    // работу по фактическому удалению элемента из списка выполнит деструктор
    // класса NodeBase
    delete base.prev;
  }
  // плохой стиль, лучше делать через итераторы, но эта концепция, наверно,
  // слишком сложна
  void PrintAll() {
    // перебор всех элементов в одном цикле
    for (NodeBase *node = base.next; node != &base; node = node->next)
      // для получения значения элемент списка приводится к типу Node*
      std::cout << static_cast< Node<ValueType>* >(node)->value;
  }
 private:
  // базовый эелемент.
  // его поле next указывает на первый элемент списка
  // поле prev указываеты на последний элемент списка
  // если список пуст, next == prev == &base
  NodeBase base;
};
 
// класс автобуса
struct Bus {
  int number;
  int route;
  //... тут наверно нужны другие поля
  Bus(int number_, int route_) : number(number_), route(route_) {}
  // переопределенный оператор для вывода на экран
  friend std::ostream& operator<<(std::ostream &stream, const Bus &bus) {
    return stream << "Bus number " << bus.number
                  << ", route: " << bus.route
                  << std::endl;
  }
};
 
int main(int argc, char *argv[]) {
  List<Bus> a; // список автобусов
  // добавим в список сто автобусов
  for (int i = 0; i < 100; ++i)
    a.PushBack(Bus(i + 1, i));
  // вывод его на экран
  a.PrintAll();
}
 
Текущее время: 23:13. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru