Вы находитесь на странице: 1из 39

Санкт-Петербург

2012
1. Цель работы
Вспомнить и применить основные приемы программирования классов и действий с
экземплярами классов на языке С++ при построения программы создания и обработки списочных
структур. Изучить самостоятельно способы построения и использования шаблонов классов и
применить их при модернизации программы создания и обработки списочных структур.

2. Постановка задачи
Задан линейный кольцевой список целочисленных значений. Построить два
однонаправленных кольцевых списка, содержащих: первый – только четные целочисленные
значения из заданного списка, а второй – только нечетные целочисленные значения из заданного
списка.
В каждом списке значения должны следовать в порядке их расположения в исходном
списке.
Работа выполняется в два этапа. На первом этапе при построении программы создаются и
применяются конкретные классы, представляющие проблемные сущности задания. На втором
этапе при модернизации программы разрабатываются и применяются шаблонные классы,
использующие шаблоны для представления проблемных частей списочных структур.

3. Формальная постановка задачи

Связь выходных и исходных данных:


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

4. Разработка структур данных и алгоритмов


Решение задачи можно разбить на этапы:
- разработка класса «Однонаправленный кольцевой список» и класса «Элемент» для него.
Однонаправленный список должен поддерживать следующие операции:
-создание
-удаление
-добавление элемента
-получение элемента
-удаление элемента

- разработка класса «Мультисписок» и класса «Элемент» для него


Мультисписок должен поддерживать следующие операции:
-добавление в основной список
-добавление элемента, находящегося в основном списке, в побочный список
-получение элемента
-удаление элемента из побочного списка
-полное удаление элемента

- реализация основной программы.

5. Модель структур данных


В качестве структур данных используется линейный список и мультисписок.
Линейный однонаправленный список:

Head – указатель на начало списка, current – указатель на текущий элемент


Мультисписок:

6 Описание классов программы


IntSingleList
параметры
метод описание Результат выполнения
входные выходные
IntSingleList() Конструктор - - Создает пустой список

IntSingleList(const Конструктор obj – копируемый


- Создает копию указанного списка
IntSingleList &obj); копирования объект

Перегрузка Список с
IntSingleList &operator obj – перемещаемый Старый список становится точно таким
оператора измененными
=(const IntSingleList &obj); объект же как и указанный
присвоения данными

~IntSingleList(); Деструктор - - Список удален из памяти

Value – добавляемое
void Add(int value); добавление - В список добавлено новое значение
значение

Position – номер
int &Get(int position); Получение элемента, который Элемент Возвращен запрашиваемый элемент
нужно получить

Поиск Value – Индекс


Возвращен индекс запрашиваемого
первого запрашиваемый запрашиваемог
int Find(int value) const; элемента
вхождения элемент о элемента

Value – удаляемый
void Remove(int value); Удаление - Запрашиваемый элемент удален
элемент
Удаление по Position – индекс
void RemoveAt(int position); - Элемент по указанному элементу удален
индексу удаляемого элемента
Количество Возвращено количество элементов
int Count() const; - Размер списка
элементов списка
Очистка
void Clear(); - - Все элементы удалены из списка
списка

MultiList
параметры
метод описание Результат выполнения
входные выходные
MultiList(); конструктор - - создан список
MultiList(const MultiList конструктор Obj – копируемый создан новый список на основе
-
&obj); копирования объект существующего
перегрузка
MultiList &operator =(const Obj – копируемый Скопированны существующий список заменен на
оператора
MultiList &obj); список й список указанный
присвоения
~MultiList(); деструктор - - список удален
добавление в
Element – добавляемое в основной список добавлен новый
void Add(int element); основной -
значение элемент
список
1 – элемент
int Add(int sublist, int добавление в sublist – подсписок; был добавлен, в указанный подсписок добавлен новый
element); подсписок element - значение 0 – элемент не элемент
был добавлен
int Remove(int element); полное element – удаляемый 1 – элемент из списка удален указанный элемент
удаление элемент был добавлен,
0 – элемент не
был добавлен
1 – элемент
удаление из
int Remove(int sublist, int sublist – подсписок; был добавлен,
указанного из подсписка удален указанный элемент
element); element - значение 0 – элемент не
подсписка
был добавлен
удаление из
sublist – подсписок;
void RemoveAt(int sublist, указанного из подсписка удален элемент по
position – индекс -
int position); подсписка по указанному индексу
элемента
индексу
void Clear(); очистка - - список очищен
ссылка на
sublist – подсписок; получен элемент из указанного
int &Get(int sublist, int элемент по
получение position – индекс подсписка удален элемент по указанному
position); указанному
элемента индексу
индексу
индекс
int Find(int sublist, int sublist – подсписок;
поиск указанного найден индекс искомого элемента
element) const; element - значение
элемента
количество
получено количество элементов в
int Count(int sublist) const; количество sublist – подсписок элементов в
указанном подсписке
подсписке
7.1 Количественные характеристики программы
Сведения о тексте:
Общая длина текста программы: 604
Количество строк комментариев: 20
Сведения о классах:
Общее количество классов, используемых в программ:4

Сведения о файлах:
Общее количество заголовочных файлов: 2
Общее количество файлов-кодов: 3

8.1 Текст программы*

Класс линейного списка:


Объявление:
#ifndef my_list
#define my_list

class IntSingleList
{
private:
class Node
{
public:
int value;
Node *next;
Node(int value);
};

Node *first;
Node *last;
int count;
public:
IntSingleList();

IntSingleList(const IntSingleList &obj);


IntSingleList &operator =(const IntSingleList &obj);
~IntSingleList();

void Add(int value);


int &Get(int position);
int Find(int value) const;
void Remove(int value);
void RemoveAt(int position);
void Clear();
int Count() const;
};

#endif
Реализация:
#include "intlist.h"
#include <assert.h>

#ifdef TALKY
#include <iostream.h>
#endif

IntSingleList::Node::Node(int value)
: value(value), next(0)
{
#ifdef TALKY
cout << "IntSingleList::Node created!" << endl;
#endif
}

IntSingleList::IntSingleList()
: first(0), last(0), count(0)
{
#ifdef TALKY
cout << "IntSingleList created!" << endl;
#endif
}

IntSingleList::IntSingleList(const IntSingleList &obj)


: count(0), first(0), last(0)
{
#ifdef TALKY
cout << "IntSingleList created!" << endl;
#endif

Node *p = obj.first;
while (p)
{
Add(p->value);
p = p->next;
}
}

IntSingleList &IntSingleList::operator =(const IntSingleList &obj)


{
Clear();
Node *current = obj.first;
for (int i = 0; i < obj.count; ++i)
{
Add(current->value);
current = current->next;
}
return *this;
}

IntSingleList::~IntSingleList()
{
#ifdef TALKY
cout << "IntSingleList deleted!" << endl;
#endif
while (first)
{
Node *deleting = first;
first = first->next;
delete deleting;
}
}

void IntSingleList::Add(int value)


{
count++;
if (!first)
{
first = last = new Node(value);
return;
}

Node *newNode = new Node(value);


last->next = newNode;
last = last->next;
}

void IntSingleList::Remove(int value)


{
if (!first)
return;

if (first->value == value)
{
Node *deleting = first;
first = first->next;
delete deleting;
count--;
return;
}

Node *c = first;
while (c->next)
{
if (c->next->value == value)
{
Node *deleting = c->next;
c->next = deleting->next;
delete deleting;
count--;
return;
}
}
}

int IntSingleList::Find(int value) const


{
int position = 0;
Node *c = first;
while (c)
{
if (c->value == value)
{
return position;
}
position++;
}
return -1;
}

int IntSingleList::Count() const


{
return count;
}

int &IntSingleList::Get(int position)


{
assert(position >= 0 && position < count);
int currentPosition = 0;
Node *currentNode = first;
while (currentPosition++ < position)
{
currentNode = currentNode->next;
}
return currentNode->value;
}

void IntSingleList::RemoveAt(int position)


{
assert(position >= 0 && position < count);
int currentPos = 0;
Node *currentNode = first;
while (currentPos++ < position - 1)
{
currentNode = currentNode->next;
}
Node *deleting = currentNode->next;
currentNode->next = deleting->next;
delete deleting;
}

void IntSingleList::Clear()
{
while (first)
{
Node *deleting = first;
first = first->next;
delete deleting;
}
count = 0;
}
Класс мультисписка:
Объявление:
#ifndef my_multilist
#define my_multilist

const int SUBLIST_COUNT = 3;


class MultiList
{
private:
const static int MAIN_SUBLIST;
class Node
{
public:
Node *next[SUBLIST_COUNT];
int value;
Node(int value);
};

Node *last[SUBLIST_COUNT];
int count[SUBLIST_COUNT];
Node *FindBefore(Node *from, int sublist, int element);
Node *RemoveNoDelete(int sublist, int element);
public:
const static int POSITIVE_SUBLIST;
const static int NONPOSITIVE_SUBLIST;

MultiList();
MultiList(const MultiList &obj);
MultiList &operator =(const MultiList &obj);
~MultiList();

void Add(int element);


int Add(int sublist, int element);

int Remove(int element);


int Remove(int sublist, int element);
void RemoveAt(int sublist, int position);
void Clear();
int &Get(int sublist, int position);
int Find(int sublist, int element) const;

int Count(int sublist) const;


};

#endif
Реализация:
#include <assert.h>
#ifdef BORLAND
#include <iostream.h>
#else
#include <iostream>
#endif
#include "mullist.h"

#ifndef BORLAND
using namespace std;
#endif

const int MultiList::MAIN_SUBLIST = 0;


const int MultiList::POSITIVE_SUBLIST = 1;
const int MultiList::NONPOSITIVE_SUBLIST = 2;

MultiList::Node::Node(int value)
: value(value)
{
#ifdef TALKY
cout << "MultiList::Node created!" << endl;
#endif
for (int i = 0; i < SUBLIST_COUNT; ++i)
{
next[i] = 0;
}
}

MultiList::Node *MultiList::FindBefore(Node *from, int sublist, int element)


{
Node *p1 = from;
Node *p = p1->next[sublist];
for (int i = 0; i < count[sublist]; ++i)
{
if (p->value == element)
return p1;
p1 = p;
p = p->next[sublist];
}
return 0;
}

MultiList::Node *MultiList::RemoveNoDelete(int sublist, int element)


{
Node *before = FindBefore(last[sublist], sublist, element);
if (!before)
return 0;
Node *del = before->next[sublist];
before->next[sublist] = del->next[sublist];
if (del == last[sublist])
last[sublist] = before;
if (del->next[sublist] == del)
last[sublist] = 0;
count[sublist]--;
return del;
}

MultiList::MultiList()
{
#ifdef TALKY
cout << "MultiList created!" << endl;
#endif
for (int i = 0; i < SUBLIST_COUNT; ++i)
{
last[i] = 0;
count[i] = 0;
}
}

MultiList::MultiList(const MultiList &obj)


{
#ifdef TALKY
cout << "MultiList created!" << endl;
#endif
int i;
for (i = 0; i < SUBLIST_COUNT; ++i)
{
last[i] = 0;
count[i] = 0;
}
for (i = 0; i < SUBLIST_COUNT; ++i)
{
Node *pp = obj.last[i]->next[i];
for (int j = 0; j < obj.Count(i); ++j)
{
Add(i, pp->value);
pp = pp->next[i];
}
}
}

MultiList &MultiList::operator =(const MultiList &obj)


{
Clear();
for (int i = 0; i < SUBLIST_COUNT; ++i)
{
Node *pp = obj.last[i]->next[i];
for (int j = 0; j < obj.Count(i); ++j)
{
Add(i, pp->value);
pp = pp->next[i];
}
}
return *this;
}

MultiList::~MultiList()
{
#ifdef TALKY
cout << "MultiList deleted!" << endl;
#endif
Clear();
}

void MultiList::Add(int element)


{
Add(MAIN_SUBLIST, element);
}

int MultiList::Add(int sublist, int element)


{
Node *newNode = 0;

if (sublist != MAIN_SUBLIST)
{
newNode = last[MAIN_SUBLIST];
do
{
newNode = FindBefore(newNode, MAIN_SUBLIST, element)->next[MAIN_SUBLIST];
}
while (newNode->next[sublist]);
}
else
newNode = new Node(element);

if (!newNode)
return 0;
count[sublist]++;

if (!last[sublist])
{
last[sublist] = newNode;
newNode->next[sublist] = newNode;
return 1;
}

Node *first = last[sublist]->next[sublist];


last[sublist]->next[sublist] = newNode;
newNode->next[sublist] = first;
last[sublist] = newNode;
return 1;
}

int MultiList::Remove(int element)


{
int result = 0;
for (int i = 0; i < SUBLIST_COUNT; ++i)
{
if (i == MAIN_SUBLIST)
continue;
if (!result)
result = Remove(i, element);
else
Remove(i, element);
}

delete RemoveNoDelete(MAIN_SUBLIST, element);


return result;
}

int MultiList::Remove(int sublist, int element)


{
return (int)RemoveNoDelete(sublist, element);
}

void MultiList::RemoveAt(int sublist, int position)


{
assert(position >= 0 && position < count[sublist]);
Node *p = last[sublist];
for (int i = 0; i < position; ++i)
p = p->next[sublist];
Node *del = p->next[sublist];
p->next[sublist] = del->next[sublist];
if (del == last[sublist])
last[sublist] = p;
if (del->next[sublist] == del)
last[sublist] = 0;
count[sublist]--;
}

void MultiList::Clear()
{
for (int i = 0; i < SUBLIST_COUNT; ++i)
{
while (Count(i))
{
RemoveAt(i, 0);
}
}
}

int &MultiList::Get(int sublist, int position)


{
assert(position >= 0 && position < count[sublist]);
Node *p = last[sublist]->next[sublist];
for (int i = 0; i < position; ++i)
{
assert(p);
p = p->next[sublist];
}
return p->value;
}

int MultiList::Find(int sublist, int element) const


{
Node *p = last[sublist]->next[sublist];
for (int i = 0; i < count[sublist]; ++i)
{
if (p->value == element)
return i;
p = p->next[sublist];
}
return -1;
}

int MultiList::Count(int sublist) const


{
return count[sublist];
}

Точка входа:
#define PART_ONE

#include <stdlib.h>
#ifdef BORLAND
#include <iostream.h>
#include <strstream.h>
typedef istrstream istringstream;
#else
#include <iostream>
#include <sstream>
#endif
#include <time.h>
#include <string.h>
#ifdef PART_ONE
#include "intlist.h"
#include "mullist.h"
typedef int Type;
#else
#include "point.h"
#include "slist.h"
#include "mlist.h"
typedef Point Type;
#endif

#ifndef BORLAND
using namespace std;
#endif

const int ADD_TO_LIST = 0;


const int REMOVE_FROM_LIST = 1;
const int SHOW_LIST = 2;
const int CREATE_MULTILIST = 3;
const int SHOW_MULTILIST = 4;
const int EXIT = 5;
const int HELP = 6;
const int SELECT_TYPE = 7;
const int CLEAN = 8;

#ifdef PART_ONE
IntSingleList list;
MultiList multilist;
typedef MultiList MultiListType;
#else
SingleList<int> iList;
MultiList<int> iMultilist;
SingleList<Point> pList;
MultiList<Point> pMultilist;
typedef MultiList<int> MultiListType;

int selectedType = 0;
const int INT = 0;
const int POINT = 1;
#endif

int ProcessCommand(int command, istream &args);


void ShowList(ostream &os);
void CreateMultilist();
void ShowMultilist(ostream &os);
void ShowSubList(ostream &os, int sublist);
void ShowHelp(ostream &os);
void AddToList(istream &is);
void RemoveFromList(istream &is);

int main()
{
srand(time(0));
ShowHelp(cout);
while (1)
{
char line[255];
cin.getline(line, 255);
istringstream str(line);
int command = 0;
str >> command;

if (!ProcessCommand(command, str))
break;
}
return 0;
}

int ProcessCommand(int command, istream &args)


{
int i;
switch(command)
{
case ADD_TO_LIST:
AddToList(args);
cout << "elements successfully added." << endl;
break;
case REMOVE_FROM_LIST:
RemoveFromList(args);
cout << "elements successfully removed." << endl;
break;
case SHOW_LIST:
ShowList(cout);
break;
case CREATE_MULTILIST:
CreateMultilist();
cout << "multilist successfully created." << endl;
break;
case SHOW_MULTILIST:
ShowMultilist(cout);
break;
case EXIT:
return 0;
case HELP:
ShowHelp(cout);
break;
#ifndef PART_ONE
case SELECT_TYPE:
int type = -1;
args >> type;
selectedType = type;
cout << "type successfully selected.";
break;
#endif
case CLEAN:
#ifdef PART_ONE
list.Clear();
#else
iList.Clear();
pList.Clear();
#endif
cout << "list successfully cleaned." << endl;
break;
default:
cout << "wrong command, try '6'." << endl;
break;
};
return 1;
}

void ShowList(ostream &os)


{
os << "{ ";
int count = -1;

#ifdef PART_ONE
count = list.Count();
#else
switch (selectedType)
{
case INT:
count = iList.Count();
break;
case POINT:
count = pList.Count();
break;
}
#endif

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


{
#ifdef PART_ONE
os << list.Get(i) << " ";
#else
switch (selectedType)
{
case INT:
os << iList.Get(i) << " ";
break;
case POINT:
os << pList.Get(i) << " ";
break;
}
#endif
}
os << "}" << endl;
}

void CreateMultilist()
{
#ifdef PART_ONE
multilist.Clear();
for (int i = 0; i < list.Count(); ++i)
{
int value = list.Get(i);
multilist.Add(value);
if (value > 0)
multilist.Add(MultiListType::POSITIVE_SUBLIST, value);
else
multilist.Add(MultiListType::NONPOSITIVE_SUBLIST, value);
}
#else
int i = -1;
switch (selectedType)
{
case INT:
iMultilist.Clear();
for (i = 0; i < iList.Count(); ++i)
{
int value = iList.Get(i);
iMultilist.Add(value);
if (value > 0)
iMultilist.Add(MultiListType::POSITIVE_SUBLIST, value);
else
iMultilist.Add(MultiListType::NONPOSITIVE_SUBLIST, value);
}
break;
case POINT:
pMultilist.Clear();
for (i = 0; i < pList.Count(); ++i)
{
Point value = pList.Get(i);
pMultilist.Add(value);
if (value > 0)
pMultilist.Add(MultiListType::POSITIVE_SUBLIST, value);
else
pMultilist.Add(MultiListType::NONPOSITIVE_SUBLIST, value);
}
break;
}
#endif
}

void ShowMultilist(ostream &os)


{
os << "{ " << endl;
os << "positive: ";
ShowSubList(os, MultiListType::POSITIVE_SUBLIST);
os << "non-positive: ";
ShowSubList(os, MultiListType::NONPOSITIVE_SUBLIST);
os << "}" << endl;
}

void ShowSubList(ostream &os, int sublist)


{
os << "{ ";
int count = -1;

#ifdef PART_ONE
count = multilist.Count(sublist);
#else
switch (selectedType)
{
case INT:
count = iMultilist.Count(sublist);
break;
case POINT:
count = pMultilist.Count(sublist);
break;
}
#endif

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


{
#ifdef PART_ONE
os << multilist.Get(sublist, i) << " ";
#else
switch (selectedType)
{
case INT:
os << iMultilist.Get(sublist, i) << " ";
break;
case POINT:
os << pMultilist.Get(sublist, i) << " ";
break;
}
#endif
}
os << "}" << endl;
}

void ShowHelp(ostream &os)


{
os << "0 - add elements to list" << endl
<< "1 - remove elements from list" << endl
<< "2 - show list" << endl
<< "3 - create multilist" << endl
<< "4 - show mutilist" << endl
<< "5 - exit" << endl
<< "6 - show this message" << endl
#ifndef PART_ONE
<< "7 - select working type (0 - int, 1 - point)" << endl
#endif
<< "8 - clean list" << endl;
}

void AddToList(istream &is)


{
while (1)
{
#ifdef PART_ONE
int arg;
if (!(is >> arg))
return;
list.Add(arg);
#else
switch (selectedType)
{
case INT:
int iArg;
if (!(is >> iArg))
return;
iList.Add(iArg);
break;
case POINT:
Point pArg;
if (!(is >> pArg))
return;
pList.Add(pArg);
break;
}
#endif
}
}

void RemoveFromList(istream &is)


{
while (!is.eof())
{
#ifdef PART_ONE
int arg;
if (!(is >> arg))
return;
list.Remove(arg);
#else
switch (selectedType)
{
case INT:
int iArg;
if (!(is >> iArg))
return;
iList.Remove(iArg);
break;
case POINT:
Point pArg;
if (!(is >> pArg))
return;
pList.Remove(pArg);
break;
}
#endif
}
}
Набор тестов
0 - add elements to list
1 - remove elements from list
2 - show list
3 - create multilist
4 - show mutilist
5 - exit
6 - show this message

0 1 -3 2 4 5 -3 -2 0
8 elements successfully added.
2
{ 1 -3 0 0 5 -3 -2 0 }
3
multilist successfully created
4
{
positive: { 1 5 }
non-positive: { -3 0 0 -3 -2 0 }
}
-------------------------------
2
{ }
3
multilist successfully created
4
{
positive: { }
non-positive: { }
}
---------------------------------
0 1 2 3
3 elements successfully added.
3
multilist successfully created
4
{
positive: { 1 2 3 }
non-positive: { }
}
Шаг 2:

6.1 Описание классов программы


Point
параметры
метод описание результат выполнения
входные выходные
Point(); конструктор - - создана новая точка
x, y –
Point(double x, создана точка с заданными
конструктор координаты -
double y); координатами
точки
xy –
создана точка с двумя одинаковыми
Point(double xy); конструктор координаты -
координатами
точки
1 – точки
int operator obj –
перегрузка оператора равны
==(const Point сравниваем получен результат сравнения 2х точек
сравнения 0 – точки не
&obj); ая точка
равны
x координата
int GetX() const; получение x координаты - получена x координата
точки
y координата
int GetY() const; получение у координаты - получена y координата
точки
1–
произведение
int operator value – получен результат сравнения
перегрузка оператора ккординат
>(double value) сравниваем произведения координат точки с
больше больше числа
const; ое число числом
0 – все
остальное
1–
произведение
int operator value – получен результат сравнения
перегрузка оператора координат
<(double value) сравниваем произведения координат точки с
меньше меньше числа
const; ое число числом
0 – все
остальное
SingleList
параметры
метод описание Результат выполнения
входные выходные
SingleList(); Конструктор - - Создает пустой список

SingleList(const SingleList<T> Конструктор obj – копируемый


- Создает копию указанного списка
&obj); копирования объект

Перегрузка Список с
SingleList<T> &operator =(const obj – перемещаемый Старый список становится точно таким
оператора измененными
SingleList<T> &obj); объект же как и указанный
присвоения данными

~SingleList(); Деструктор - - Список удален из памяти


Value – добавляемое
void Add(const T &value); добавление - В список добавлено новое значение
значение

Position – номер
T &Get(int position); Получение элемента, который Элемент Возвращен запрашиваемый элемент
нужно получить

Поиск Value – Индекс


Возвращен индекс запрашиваемого
первого запрашиваемый запрашиваемог
int Find(const T &value) const; элемента
вхождения элемент о элемента

Value – удаляемый
void Remove(const T &value); Удаление - Запрашиваемый элемент удален
элемент
Удаление по Position – индекс
void RemoveAt(int position); - Элемент по указанному элементу удален
индексу удаляемого элемента
Количество Возвращено количество элементов
int Count() const; - Размер списка
элементов списка
Очистка
void Clear(); - - Все элементы удалены из списка
списка
MultiList
параметры
метод описание Результат выполнения
входные выходные
MultiList(); конструктор - - создан список
MultiList(const MultiList<T> конструктор Obj – копируемый создан новый список на основе
-
&obj); копирования объект существующего
перегрузка
MultiList<T> &operator Obj – копируемый Скопированны существующий список заменен на
оператора
=(const MultiList<T> &obj); список й список указанный
присвоения
~MultiList(); деструктор - - список удален
добавление в
Element – добавляемое в основной список добавлен новый
void Add(const T &element); основной -
значение элемент
список
1 – элемент
int Add(int sublist, const T добавление в sublist – подсписок; был добавлен, в указанный подсписок добавлен новый
&element); подсписок element - значение 0 – элемент не элемент
был добавлен
1 – элемент
int Remove(const T полное element – удаляемый был добавлен,
из списка удален указанный элемент
&element); удаление элемент 0 – элемент не
был добавлен
1 – элемент
удаление из
int Remove(int sublist, const sublist – подсписок; был добавлен,
указанного из подсписка удален указанный элемент
T &element); element - значение 0 – элемент не
подсписка
был добавлен
удаление из
sublist – подсписок;
void RemoveAt(int sublist, указанного из подсписка удален элемент по
position – индекс -
int position); подсписка по указанному индексу
элемента
индексу
void Clear(); очистка - - список очищен
ссылка на
sublist – подсписок; получен элемент из указанного
T &Get(int sublist, int элемент по
получение position – индекс подсписка удален элемент по указанному
position); указанному
элемента индексу
индексу
индекс
int Find(int sublist, const T sublist – подсписок;
поиск указанного найден индекс искомого элемента
&element) const; element - значение
элемента
количество
получено количество элементов в
int Count(int sublist) const; количество sublist – подсписок элементов в
указанном подсписке
подсписке

8.2 Текст программы


Линейный список
Объявление:
#ifndef my_slist
#define my_slist

#include <assert.h>

#ifdef TALKY
#include <iostream.h>
#endif

#ifndef BORLAND
using namespace std;
#endif

template<class T>
class SingleListNode
{
public:
T value;
SingleListNode<T> *next;
SingleListNode(const T &value);
};

template<class T>
class SingleList
{
private:

SingleListNode<T> *first;
SingleListNode<T> *last;
int count;
public:
SingleList();

SingleList(const SingleList<T> &obj);


SingleList<T> &operator =(const SingleList<T> &obj);
~SingleList();

void Add(const T &value);


T &Get(int position);
int Find(const T &value) const;
void Remove(const T &value);
void RemoveAt(int position);
void Clear();
int Count() const;
};

#include "slist.hpp"

#endif

Реализация:
template<class T>
SingleListNode<T>::SingleListNode(const T &value)
: value(value), next(0)
{
#ifdef TALKY
cout << "SingleListNode created!" << endl;
#endif
}

template<class T>
SingleList<T>::SingleList()
: first(0), last(0), count(0)
{
#ifdef TALKY
cout << "SingleList created!" << endl;
#endif
}

template<class T>
SingleList<T>::SingleList(const SingleList<T> &obj)
: count(0), first(0), last(0)
{
#ifdef TALKY
cout << "SingleList created!" << endl;
#endif

SingleListNode<T> *p = obj.first;
while (p)
{
Add(p->value);
p = p->next;
}
}
template<class T>
SingleList<T> &SingleList<T>::operator =(const SingleList<T> &obj)
{
Clear();
SingleListNode<T> *current = obj.first;
for (int i = 0; i < obj.count; ++i)
{
Add(current->value);
current = current->next;
}
return *this;
}

template<class T>
SingleList<T>::~SingleList()
{
#ifdef TALKY
cout << "SingleList deleted!" << endl;
#endif
while (first)
{
SingleListNode<T> *deleting = first;
first = first->next;
delete deleting;
}
}

template<class T>
void SingleList<T>::Add(const T &value)
{
count++;
if (!first)
{
first = last = new SingleListNode<T>(value);
return;
}

SingleListNode<T> *newNode = new SingleListNode<T>(value);


last->next = newNode;
last = last->next;
}

template<class T>
void SingleList<T>::Remove(const T &value)
{
if (!first)
return;

if (first->value == value)
{
SingleListNode<T> *deleting = first;
first = first->next;
delete deleting;
count--;
return;
}

SingleListNode<T> *c = first;
while (c->next)
{
if (c->next->value == value)
{
SingleListNode<T> *deleting = c->next;
c->next = deleting->next;
delete deleting;
count--;
return;
}
}
}

template<class T>
int SingleList<T>::Find(const T &value) const
{
int position = 0;
SingleListNode<T> *c = first;
while (c)
{
if (c->value == value)
{
return position;
}
position++;
}
return -1;
}

template<class T>
int SingleList<T>::Count() const
{
return count;
}

template<class T>
T &SingleList<T>::Get(int position)
{
assert(position >= 0 && position < count);
int currentPosition = 0;
SingleListNode<T> *currentNode = first;
while (currentPosition++ < position)
{
currentNode = currentNode->next;
}
return currentNode->value;
}

template<class T>
void SingleList<T>::RemoveAt(int position)
{
assert(position >= 0 && position < count);
int currentPos = 0;
SingleListNode<T> *currentNode = first;
while (currentPos++ < position - 1)
{
currentNode = currentNode->next;
}
SingleListNode<T> *deleting = currentNode->next;
currentNode->next = deleting->next;
delete deleting;
}

template<class T>
void SingleList<T>::Clear()
{
while (first)
{
SingleListNode<T> *deleting = first;
first = first->next;
delete deleting;
}
count = 0;
}
Мультисписок:
Объявление:
#ifndef my_multilist
#define my_multilist
#include <assert.h>
#ifdef BORLAND
#include <iostream.h>
#else
#include <iostream>
using namespace std;
#endif

const int SUBLIST_COUNT = 3;

template<class T>
class MultiNode
{
public:
MultiNode<T> *next[SUBLIST_COUNT];
T value;
MultiNode(const T &value);
};

template<class T>
class MultiList
{
private:
const static int MAIN_SUBLIST;

MultiNode<T> *last[SUBLIST_COUNT];
int count[SUBLIST_COUNT];
MultiNode<T> *FindBefore(MultiNode<T> *from, int sublist, const T &element);
MultiNode<T> *RemoveNoDelete(int sublist, const T &element);
public:
const static int POSITIVE_SUBLIST;
const static int NONPOSITIVE_SUBLIST;

MultiList();
MultiList(const MultiList<T> &obj);
MultiList<T> &operator =(const MultiList<T> &obj);
~MultiList();

void Add(const T &element);


int Add(int sublist, const T &element);

int Remove(const T &element);


int Remove(int sublist, const T &element);
void RemoveAt(int sublist, int position);
void Clear();

T &Get(int sublist, int position);


int Find(int sublist, const T &element) const;

int Count(int sublist) const;


};

#include "mlist.hpp"

#endif
Реализация:
template<class T>
const int MultiList<T>::MAIN_SUBLIST = 0;
template<class T>
const int MultiList<T>::POSITIVE_SUBLIST = 1;
template<class T>
const int MultiList<T>::NONPOSITIVE_SUBLIST = 2;

template<class T>
MultiNode<T>::MultiNode(const T &value)
: value(value)
{
#ifdef TALKY
cout << "MultiNode created!" << endl;
#endif
for (int i = 0; i < SUBLIST_COUNT; ++i)
{
next[i] = 0;
}
}

template<class T>
MultiNode<T> *MultiList<T>::FindBefore(MultiNode<T> *from, int sublist, const T &element)
{
MultiNode<T> *p1 = from;
MultiNode<T> *p = p1->next[sublist];
for (int i = 0; i < count[sublist]; ++i)
{
if (p->value == element)
return p1;
p1 = p;
p = p->next[sublist];
}
return 0;
}

template<class T>
MultiNode<T> *MultiList<T>::RemoveNoDelete(int sublist, const T &element)
{
MultiNode<T> *before = FindBefore(last[sublist], sublist, element);
if (!before)
return 0;
MultiNode<T> *del = before->next[sublist];
before->next[sublist] = del->next[sublist];
if (del == last[sublist])
last[sublist] = before;
if (del->next[sublist] == del)
last[sublist] = 0;
count[sublist]--;
return del;
}

template<class T>
MultiList<T>::MultiList()
{
#ifdef TALKY
cout << "MultiList created!" << endl;
#endif
for (int i = 0; i < SUBLIST_COUNT; ++i)
{
last[i] = 0;
count[i] = 0;
}
}

template<class T>
MultiList<T>::MultiList(const MultiList<T> &obj)
{
#ifdef TALKY
cout << "MultiList created!" << endl;
#endif
int i;
for (i = 0; i < SUBLIST_COUNT; ++i)
{
last[i] = 0;
count[i] = 0;
}
for (i = 0; i < SUBLIST_COUNT; ++i)
{
MultiNode<T> *pp = obj.last[i]->next[i];
for (int j = 0; j < obj.Count(i); ++j)
{
Add(i, pp->value);
pp = pp->next[i];
}
}
}

template<class T>
MultiList<T> &MultiList<T>::operator =(const MultiList<T> &obj)
{
Clear();
for (int i = 0; i < SUBLIST_COUNT; ++i)
{
MultiNode<T> *pp = obj.last[i]->next[i];
for (int j = 0; j < obj.Count(i); ++j)
{
Add(i, pp->value);
pp = pp->next[i];
}
}
return *this;
}

template<class T>
MultiList<T>::~MultiList()
{
#ifdef TALKY
cout << "MultiList deleted!" << endl;
#endif
Clear();
}

template<class T>
void MultiList<T>::Add(const T &element)
{
Add(MAIN_SUBLIST, element);
}

template<class T>
int MultiList<T>::Add(int sublist, const T &element)
{
MultiNode<T> *newNode = 0;

if (sublist != MAIN_SUBLIST)
{
newNode = last[MAIN_SUBLIST];
do
{
newNode = FindBefore(newNode, MAIN_SUBLIST, element)->next[MAIN_SUBLIST];
}
while (newNode->next[sublist]);
}
else
newNode = new MultiNode<T>(element);

if (!newNode)
return 0;
count[sublist]++;
if (!last[sublist])
{
last[sublist] = newNode;
newNode->next[sublist] = newNode;
return 1;
}

MultiNode<T> *first = last[sublist]->next[sublist];


last[sublist]->next[sublist] = newNode;
newNode->next[sublist] = first;
last[sublist] = newNode;
return 1;
}

template<class T>
int MultiList<T>::Remove(const T &element)
{
int result = 0;
for (int i = 0; i < SUBLIST_COUNT; ++i)
{
if (i == MAIN_SUBLIST)
continue;
if (!result)
result = Remove(i, element);
else
Remove(i, element);
}

delete RemoveNoDelete(MAIN_SUBLIST, element);


return result;
}

template<class T>
int MultiList<T>::Remove(int sublist, const T &element)
{
return (int)RemoveNoDelete(sublist, element);
}

template<class T>
void MultiList<T>::RemoveAt(int sublist, int position)
{
assert(position >= 0 && position < count[sublist]);
MultiNode<T> *p = last[sublist];
for (int i = 0; i < position; ++i)
p = p->next[sublist];
MultiNode<T> *del = p->next[sublist];
p->next[sublist] = del->next[sublist];
if (del == last[sublist])
last[sublist] = p;
if (del->next[sublist] == del)
last[sublist] = 0;
count[sublist]--;
}

template<class T>
void MultiList<T>::Clear()
{
for (int i = 0; i < SUBLIST_COUNT; ++i)
{
while (Count(i))
{
RemoveAt(i, 0);
}
}
}

template<class T>
T &MultiList<T>::Get(int sublist, int position)
{
assert(position >= 0 && position < count[sublist]);
MultiNode<T> *p = last[sublist]->next[sublist];
for (int i = 0; i < position; ++i)
{
assert(p);
p = p->next[sublist];
}
return p->value;
}

template<class T>
int MultiList<T>::Find(int sublist, const T &element) const
{
MultiNode<T> *p = last[sublist]->next[sublist];
for (int i = 0; i < count[sublist]; ++i)
{
if (p->value == element)
return i;
p = p->next[sublist];
}
return -1;
}

template<class T>
int MultiList<T>::Count(int sublist) const
{
return count[sublist];
}

Точка:
Объявление:
#ifndef my_point
#define my_point

#ifdef BORLAND
#include <iostream.h>
#else
#include <iostream>
#endif

#ifndef BORLAND
using namespace std;
#endif

class Point
{
private:
double x;
double y;
public:
Point();
Point(double x, double y);
Point(double xy);
int operator ==(const Point &obj);
int GetX() const;
int GetY() const;
int operator >(double value) const;
int operator <(double value) const;

friend ostream &operator <<(ostream &os, Point &p);


friend istream &operator >>(istream &is, Point &p);
};

Point *ReadPoint(istream &is);


void SkipSpaces(istream &is);

#endif
Реализация:
#include "point.h"
#include <ctype.h>

Point::Point()
: x(0), y(0)
{
#ifdef TALKY
cout << "Point created!" << endl;
#endif
}

Point::Point(double x, double y)
: x(x), y(y)
{
#ifdef TALKY
cout << "Point created!" << endl;
#endif
}

Point::Point(double xy)
: x(xy), y(xy)
{
#ifdef TALKY
cout << "Point created!" << endl;
#endif
}

int Point::operator ==(const Point &obj)


{
return x == obj.x && y == obj.y;
}

int Point::GetX() const


{
return x;
}

int Point::GetY() const


{
return y;
}

int Point::operator >(double value) const


{
return x * y > value;
}

int Point::operator <(double value) const


{
return x * y < value;
}

ostream &operator <<(ostream &os, Point &p)


{
return os << "{ " << p.GetX() << ", " << p.GetY() << " }";
}

istream &operator >>(istream &is, Point &p)


{
Point *readed = ReadPoint(is);
is.clear(istream::goodbit);
if (!readed)
{
is.clear(istream::eofbit);
return is;
}
p = *readed;
return is;
}

Point *ReadPoint(istream &is)


{
SkipSpaces(is);
if(is.peek() != '{')
return 0;
is.get();
SkipSpaces(is);
double x = 0;
is >> x;
SkipSpaces(is);
if(is.peek() != ',')
return 0;
is.get();
SkipSpaces(is);
double y = 0;
is >> y;
SkipSpaces(is);
if(is.peek() != '}')
return 0;
is.get();
return new Point(x, y);
}

void SkipSpaces(istream &is)


{
while(isspace(is.peek()))
is.get();
}

Точка входа:
#define PART_ONE

#include <stdlib.h>
#ifdef BORLAND
#include <iostream.h>
#include <strstream.h>
typedef istrstream istringstream;
#else
#include <iostream>
#include <sstream>
#endif
#include <time.h>
#include <string.h>
#ifdef PART_ONE
#include "intlist.h"
#include "mullist.h"
typedef int Type;
#else
#include "point.h"
#include "slist.h"
#include "mlist.h"
typedef Point Type;
#endif

#ifndef BORLAND
using namespace std;
#endif

const int ADD_TO_LIST = 0;


const int REMOVE_FROM_LIST = 1;
const int SHOW_LIST = 2;
const int CREATE_MULTILIST = 3;
const int SHOW_MULTILIST = 4;
const int EXIT = 5;
const int HELP = 6;
const int SELECT_TYPE = 7;
const int CLEAN = 8;

#ifdef PART_ONE
IntSingleList list;
MultiList multilist;
typedef MultiList MultiListType;
#else
SingleList<int> iList;
MultiList<int> iMultilist;
SingleList<Point> pList;
MultiList<Point> pMultilist;
typedef MultiList<int> MultiListType;

int selectedType = 0;
const int INT = 0;
const int POINT = 1;
#endif

int ProcessCommand(int command, istream &args);


void ShowList(ostream &os);
void CreateMultilist();
void ShowMultilist(ostream &os);
void ShowSubList(ostream &os, int sublist);
void ShowHelp(ostream &os);
void AddToList(istream &is);
void RemoveFromList(istream &is);

int main()
{
srand(time(0));
ShowHelp(cout);
while (1)
{
char line[255];
cin.getline(line, 255);
istringstream str(line);
int command = 0;
str >> command;

if (!ProcessCommand(command, str))
break;
}
return 0;
}

int ProcessCommand(int command, istream &args)


{
int i;
switch(command)
{
case ADD_TO_LIST:
AddToList(args);
cout << "elements successfully added." << endl;
break;
case REMOVE_FROM_LIST:
RemoveFromList(args);
cout << "elements successfully removed." << endl;
break;
case SHOW_LIST:
ShowList(cout);
break;
case CREATE_MULTILIST:
CreateMultilist();
cout << "multilist successfully created." << endl;
break;
case SHOW_MULTILIST:
ShowMultilist(cout);
break;
case EXIT:
return 0;
case HELP:
ShowHelp(cout);
break;
#ifndef PART_ONE
case SELECT_TYPE:
int type = -1;
args >> type;
selectedType = type;
cout << "type successfully selected.";
break;
#endif
case CLEAN:
#ifdef PART_ONE
list.Clear();
#else
iList.Clear();
pList.Clear();
#endif
cout << "list successfully cleaned." << endl;
break;
default:
cout << "wrong command, try '6'." << endl;
break;
};
return 1;
}

void ShowList(ostream &os)


{
os << "{ ";
int count = -1;

#ifdef PART_ONE
count = list.Count();
#else
switch (selectedType)
{
case INT:
count = iList.Count();
break;
case POINT:
count = pList.Count();
break;
}
#endif

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


{
#ifdef PART_ONE
os << list.Get(i) << " ";
#else
switch (selectedType)
{
case INT:
os << iList.Get(i) << " ";
break;
case POINT:
os << pList.Get(i) << " ";
break;
}
#endif
}
os << "}" << endl;
}

void CreateMultilist()
{
#ifdef PART_ONE
multilist.Clear();
for (int i = 0; i < list.Count(); ++i)
{
int value = list.Get(i);
multilist.Add(value);
if (value > 0)
multilist.Add(MultiListType::POSITIVE_SUBLIST, value);
else
multilist.Add(MultiListType::NONPOSITIVE_SUBLIST, value);
}
#else
int i = -1;
switch (selectedType)
{
case INT:
iMultilist.Clear();
for (i = 0; i < iList.Count(); ++i)
{
int value = iList.Get(i);
iMultilist.Add(value);
if (value > 0)
iMultilist.Add(MultiListType::POSITIVE_SUBLIST, value);
else
iMultilist.Add(MultiListType::NONPOSITIVE_SUBLIST, value);
}
break;
case POINT:
pMultilist.Clear();
for (i = 0; i < pList.Count(); ++i)
{
Point value = pList.Get(i);
pMultilist.Add(value);
if (value > 0)
pMultilist.Add(MultiListType::POSITIVE_SUBLIST, value);
else
pMultilist.Add(MultiListType::NONPOSITIVE_SUBLIST, value);
}
break;
}
#endif
}

void ShowMultilist(ostream &os)


{
os << "{ " << endl;
os << "positive: ";
ShowSubList(os, MultiListType::POSITIVE_SUBLIST);
os << "non-positive: ";
ShowSubList(os, MultiListType::NONPOSITIVE_SUBLIST);
os << "}" << endl;
}

void ShowSubList(ostream &os, int sublist)


{
os << "{ ";
int count = -1;

#ifdef PART_ONE
count = multilist.Count(sublist);
#else
switch (selectedType)
{
case INT:
count = iMultilist.Count(sublist);
break;
case POINT:
count = pMultilist.Count(sublist);
break;
}
#endif

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


{
#ifdef PART_ONE
os << multilist.Get(sublist, i) << " ";
#else
switch (selectedType)
{
case INT:
os << iMultilist.Get(sublist, i) << " ";
break;
case POINT:
os << pMultilist.Get(sublist, i) << " ";
break;
}
#endif
}
os << "}" << endl;
}

void ShowHelp(ostream &os)


{
os << "0 - add elements to list" << endl
<< "1 - remove elements from list" << endl
<< "2 - show list" << endl
<< "3 - create multilist" << endl
<< "4 - show mutilist" << endl
<< "5 - exit" << endl
<< "6 - show this message" << endl
#ifndef PART_ONE
<< "7 - select working type (0 - int, 1 - point)" << endl
#endif
<< "8 - clean list" << endl;
}

void AddToList(istream &is)


{
while (1)
{
#ifdef PART_ONE
int arg;
if (!(is >> arg))
return;
list.Add(arg);
#else
switch (selectedType)
{
case INT:
int iArg;
if (!(is >> iArg))
return;
iList.Add(iArg);
break;
case POINT:
Point pArg;
if (!(is >> pArg))
return;
pList.Add(pArg);
break;
}
#endif
}
}

void RemoveFromList(istream &is)


{
while (!is.eof())
{
#ifdef PART_ONE
int arg;
if (!(is >> arg))
return;
list.Remove(arg);
#else
switch (selectedType)
{
case INT:
int iArg;
if (!(is >> iArg))
return;
iList.Remove(iArg);
break;
case POINT:
Point pArg;
if (!(is >> pArg))
return;
pList.Remove(pArg);
break;
}
#endif
}
}

Набор тестов
0 - add elements to list
1 - remove elements from list
2 - show list
3 - create multilist
4 - show mutilist
5 - exit
6 - show this message
7 - select working type (0 - int, 1 - point)
8 - clean list
0 1 -1 0
elements successfully added.
2
{ 1 -1 0 }
3
multilist successfully created.
4
{
positive: { 1 }
non-positive: { -1 0 }
}
8
list successfully cleaned.
0 1 2
elements successfully added.
2
{ 1 2 }
3
multilist successfully created.
4
{
positive: { 1 2 }
non-positive: { }
}
8
list successfully cleaned.
2
{ }
3
multilist successfully created.
4
{
positive: { }
non-positive: { }
}
7 1
1 type successfully selected.
0 {-1, 1} {1, 1} {0, 1}
elements successfully added.
2
{ { -1, 1 } { 1, 1 } { 0, 1 } }
3
multilist successfully created.
4
{
positive: { { 1, 1 } }
non-positive: { { -1, 1 } { 0, 1 } }
}
8
list successfully cleaned.
2
{ }
3
multilist successfully created.
4
{
positive: { }
non-positive: { }
}
0 {1, 1} {1, 2}
elements successfully added.
2
{ { 1, 1 } { 1, 2 } }
3
multilist successfully created.
4
{
positive: { { 1, 1 } { 1, 2 } }
non-positive: { }
}
Задан однонаправленный список целочисленных
значений
Построить на его основе мультисписок,
содержащий, кроме заданного списка, два
кольцевых однонаправленных списка:
-первый – только положительные значения из
исходного списка, а
-второй – только неположительные значения из
исходного списка

Задан линейный однонаправленный список


целочисленных значений
Построить на его основе мультисписок,
содержащий, кроме заданного списка, два
кольцевых однонаправленных списка:
-первый – только положительные значения
из исходного списка, а
-второй – только неположительные
значения из исходного списка