Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/4: Рейтинг темы: голосов - 4, средняя оценка - 5.00
0 / 0 / 0
Регистрация: 01.06.2017
Сообщений: 31

Как отсортировать данный шаблонный двусвязный класс?

04.06.2017, 15:40. Показов 815. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Пишу программу " Моя записная книжка" Необходимо сделать сортировку по разным полям. Я не могу понять как это реализовать. Помогите пожалуйста.

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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
#include <iostream>
#include <string>
#include <cstdlib>
 
 
// базовый класс элемента связного списка
// не содержит данных, содержит часть логики
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>
struct Iterator {
private:
    // собственно, элемент связного списка, который хранит итератор
    NodeBase *node;
public:
    // создание итератора при помощи элемента связного списка
    explicit Iterator(NodeBase *node_) : node(node_) {}
    // создание копированием с другого итератора
    Iterator(const Iterator &other) : node(other.node) {}
    // получение значения элемента связного списка
    ValueType &operator*() {
        return static_cast<Node<ValueType>*>(node)->value;
    }
    // присваивание итератору другого итератора
    Iterator &operator=(const Iterator &other) {
        if (&other != this)
            node = other.node;
        return *this;
    }
    // переход к следующему элементу (постфиксный)
    Iterator &operator++() {
        node = node->next;
        return *this;
    }
    // переход к предыдущему элементу (постфиксный)
    Iterator &operator--() {
        node = node->prev;
        return *this;
    }
    // проверка итераторов на равенство
    bool operator==(const Iterator &other) {
        return node == other.node;
    }
    // ... на неравенство
    bool operator!=(const Iterator &other) {
        return node != other.node;
    }
 
};
 
// собственно, шаблон двусвязного списка
// смотрите, как мало собственно кода, если убрать комментарии
template <typename ValueType>
class List {
private:
    // базовый эелемент.
    // его поле next указывает на первый элемент списка
    // поле prev указываеты на последний элемент списка
    // если список пуст, next == prev == &base
    NodeBase base;
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;
    }
    // печать данных по условию
    template <class Predicate> // класс или функция, принимающие параметром
                               // ValueType и возвращающая true или false.
    void PrintIf(Predicate condition) {
        // цикл по всем элементам массива
        for (NodeBase *node = base.next; node != &base; node = node->next)
            // если условие выполняется
            if (condition(static_cast<Node<ValueType>*>(node)->value))
                // вывести значение
                std::cout << static_cast<Node<ValueType>*>(node)->value;
    }
    // итератор на начало связного списка
    Iterator<ValueType> Begin() {
        // началом связного списка является элемент, на который указывает
        // поле next переменной base
        return Iterator<ValueType>(base.next);
    }
    // итератор на элемент связного списка _после_ последнего
    Iterator<ValueType> End() {
        // элементом за связным списком является само поле base
        return Iterator<ValueType>(&base);
    }
    // поиск элемента в списке
    // принимает параметрами первый элемент и последний элемент, в
    // которых надо искать список
    // и функтор, принимающий значение элемента и возвращающая true или
    // false
    // возвращает итератор найденного элемента или последний параметр
    // если элемента не найдено
    template <class Predicate>
    Iterator<ValueType> Search(Iterator<ValueType> begin,
        Iterator<ValueType> end,
        Predicate condition) {
        for (; begin != end; ++begin)
            if (condition(*begin)) break;
        return begin;
    }
 
};
 
// класс человек
struct Person {
    std::string surname;
    std::string name;
    std::string otch;
    int phone;
    int date[3];
    
    
    Person(std::string surname_, std::string name_, std::string otch_,  int phone_, int date_[3])
        : surname(surname_), name(name_), otch(otch_), phone(phone_) {
        date[0] = date_[0];
        date[1] = date_[1];
        date[2] = date_[2];
    }  // переопределенный оператор для вывода на экран
    
    friend std::ostream& operator<<(std::ostream &stream, const Person &person) {
        return stream << 
             " Surname: " << person.surname
            << ", Name: " << person.name
            << ", Otch: " << person.otch
            << ", Phone : " << person.number
            << ", Date: " << person.date[0]<<'.'<<person.date[1] << '.' << person.date[2] 
            << std::endl;
    }
    // класс-функтор для поиска 
    struct IsPhone {
        // запоминаем параметр в классе
        IsPhone(int parameter_) : parameter(parameter_) {}
        // оператор-функтор для сравнения параметра
        bool operator()(const Person &person) {
            return person.phone == parameter;
        }
        int parameter; // параметр
    };
 
    // класс-функтор для поиска по дате рождения
    struct IsDate {
        // запоминаем параметр в классе
        IsDate(int parameter_[3]) 
        {
            for (int i = 0; i < 3; i++)
                parameter[i] = parameter_[i];
        }
        // оператор-функтор для сравнения параметра
        bool operator()(const Person &person) {
            if (person.date[0] == parameter[0] && person.date[1] == parameter[1] && person.date[2] == parameter[2])
                return true;
                else return false;
        }
        int parameter[3]; // параметр
    };
 
    // класс-функтор для поиска 
    struct IsSurname {
        // запоминаем параметр в классе
        IsSurname(const std::string &parameter_) : parameter(parameter_) {}
        // оператор-функтор для сравнения параметра
        bool operator()(const Person &person) {
            return person.surname == parameter;
        }
        std::string parameter; // параметр
    };
 
    struct IsName {
        // запоминаем параметр в классе
        IsName(const std::string &parameter_) : parameter(parameter_) {}
        // оператор-функтор для сравнения параметра
        bool operator()(const Person &person) {
            return person.name == parameter;
        }
        std::string parameter; // параметр
    };
 
};
 
int main(int argc, char *argv[]) {
    
    List<Person> a; 
        
    int n = 0;
    while (!0)
    {
        std::cout << "\n Menu \n\
1) New person \n\
2) Print notebook \n\
3) Search\n\
4) Sorting \n\
5) Delete \n\
0) Exit\n";
        std::cin >> n;
        if (n == 1) {
            std::string surname, name, otch;
            int nomer, date[3];
                        std::cout << "Surname... ";
            std::cin >> surname;
            std::cout << "Name... ";
            std::cin >> name;
            std::cout << "otch... ";
            std::cin >> otch;
            std::cout << "Nom... ";
            std::cin >> nomer;
            std::cout << "Date... ";
            for (int i=0;i<3;i++)
            std::cin >> date[i];
                    
            a.PushBack(Person(surname, name, otch, nomer, date));
        }
        if (n == 2) a.PrintAll();
        
        if (n == 3) {
            std::cout << "\nSearch\n\
            1) by Surname\n\
            2) by Name\n\
            3) by Phone\n\
            4) by birthday\n\
            0) Exit\n";
            int n2;
            std::cin >> n2;
            if (n2 == 1)
            {   std::string req;
                std::cin >> req;
                Iterator<Person> b = a.Search(a.Begin(), a.End(), Person::IsSurname(req));
                if (b != a.End())
                    std::cout << *b;
            }
 
            if (n2 == 2)
            {   std::string req;
            std::cin >> req;
            Iterator<Person> b = a.Search(a.Begin(), a.End(), Person::IsName(req));
            if (b != a.End())
                std::cout << *b;
            }
            
            if (n2 == 3)
            {   int req;
                std::cin >> req;
                Iterator<Person> b = a.Search(a.Begin(), a.End(), Person::IsPhone(req));
                if (b != a.End())
                    std::cout << *b;
            }
 
            if (n2 == 4)
            {   int req[3];
            std::cout << "Date... ";
            for (int i = 0; i<3; i++)
                std::cin >> req[i];
                Iterator<Person> b = a.Search(a.Begin(), a.End(), Person::IsDate(req));
                if (b != a.End())
                    std::cout << *b;
            }
 
            
        }
            
        if (n == 4) {
         
        }
        /*
        if (n == 0) {
            mybook.saveFile("struct.txt");
            return 0;
        }
        */
    }
    system("pause");
    return 0;
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
04.06.2017, 15:40
Ответы с готовыми решениями:

Как отсортировать двусвязный список?
Здравствуйте, имеется двусвязный список, в узлах - информация о поездах и нужно его отсортировать по &quot;возростанию&quot; городов. Мой...

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

Как расположить шаблонный класс в разных файлах?
Есть некоторый класс A, он размещен в разных файлах так: main.cpp : #include &lt;iostream&gt; #include &quot;a.h&quot; int main() { ...

4
с++
1282 / 523 / 225
Регистрация: 15.07.2015
Сообщений: 2,562
04.06.2017, 16:53
можно сделать алгоритм сортировки или же стандартными сортировка воспользоваться к примеру sort() c библиотеки algorithm
Алгоритмы сортировок
0
0 / 0 / 0
Регистрация: 01.06.2017
Сообщений: 31
04.06.2017, 17:00  [ТС]
Цитата Сообщение от Antikl Посмотреть сообщение
можно сделать алгоритм сортировки или же стандартными сортировка воспользоваться к примеру sort() c библиотеки algorithm
Алгоритмы сортировок
Библиотеками пользоваться нельзя. а ту ссылку которую вы скинули я там не нашёл сортировки для списков
0
с++
1282 / 523 / 225
Регистрация: 15.07.2015
Сообщений: 2,562
04.06.2017, 17:06
Цитата Сообщение от Степан174174 Посмотреть сообщение
сортировки для списков
то как бы их алгоритм а для списка их нужно приспособить
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
#include <iostream>
#include <cstdlib>
#include <ctime>
 
typedef struct Node
{    
    int data;
    Node *next;
} *PNode;
 
void push_front( PNode &head, int data )
{
    head = new Node { data, head };
}
 
std::ostream & display( const PNode &head, std::ostream &os = std::cout )
{
    for ( PNode current = head; current; current = current->next )
    {
        os << current->data << ' ';
    }
    return os;
}
 
void SortedInsert( PNode &head, PNode node )
{
    if ( !head || node->data < head->data )
    {
        node->next = head;
        head = node;
    }
    else
    {
        PNode current = head;
        while ( current->next && !( node->data < current->next->data ) )
        {
            current = current->next;
        }
 
        node->next = current->next;
        current->next = node;
    }
}
 
PNode InsertionSort( PNode &head )
{
    PNode result = nullptr;
 
    while ( head )
    {
        PNode node = head;
        head = head->next;
        SortedInsert( result, node );
    }
 
    return result;
}
 
int main() 
{
    const size_t N = 10;
    PNode head = nullptr;
 
    std::srand( ( unsigned int )std::time( nullptr ) );
 
    for ( size_t i = 0; i < N; i++ ) push_front( head, std::rand() % N );
 
    display( head ) << std::endl;    
 
    PNode head2 = InsertionSort( head );
 
    display( head2 ) << std::endl;    
 
    return 0;
}
0
0 / 0 / 0
Регистрация: 01.06.2017
Сообщений: 31
04.06.2017, 17:12  [ТС]
Цитата Сообщение от Antikl Посмотреть сообщение
то как бы их алгоритм а для списка их нужно приспособить
[
А как приспособить? не совсем понимаю((
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
04.06.2017, 17:12
Помогаю со студенческими работами здесь

Передать шаблонный класс, как параметр шаблона
нужно не используя stl написать аналог класса list. написал болванку и застрял template&lt;class C&gt; class node{ protected: C...

Как правильно подключить шаблонный класс (VS2008)?
Добрый день! Помогите в подключении шаблонного класса в Visual Studio 2008 Professional. Создал консольный проект,в заголовочном...

Как корректно удалить шаблонный класс CList?
Создаю указатель на класс CList в заголовочном файле. С помощью этого указателя динамически создаю нужное количество (N) объектов класса...

Как вынести метод возвращающий шаблонный класс в из hpp в cpp?
Есть код в заголовоном файле: template&lt;class T,typename Ptr&gt; class LINQ { private: Ptr begin; Ptr end; ...

Как создать шаблонный класс-массив для хранения объектов?
Есть абстрактный класс Figure. Есть два производных от него класа: Field i TicTаc. И есть шаблонный класс Arr. У Field'и есть поле...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru