Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программирование на C / C++ / Викентьева О.Л., Гусин А.Н., Полякова О.А. Программирование на языке С++. Лабораторный практикум.doc
Скачиваний:
179
Добавлен:
02.05.2014
Размер:
13.62 Mб
Скачать

2.1. Двунаправленные списки

Двунаправленный список имеет два адресных поля, которые указывают на следующий элемент списка и на предыдущий. Поэтому двигаться по такому списку можно как слева направо, так и справа налево.

//формирование двунаправленного списка

struct point

{

char *key;//адресное поле – динамическая строка

point *next;//указатель на следующий элемент

point *pred;//указатель на предыдущий элемент

};

point* make_point()

//создание одного элемента

{

point*p=new(point);

p->next=0;p->pred=0;//обнуляем указатели

char s[50];

cout<<"\nEnter string:";

cin>>s;

p->key=new char[strlen(s)+1];//выделение памяти под строку

strcpy(p->key,s);

return p;

}

point*make_list(int n)

//создание списка

{

point *p,*beg;

beg=make_point();//создаем первый элемент

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

{

p=make_point();//создаем один элемент

//добавление элемента в начало списка

p->next=beg;//связываем р с первым элементом

beg->pred=p;//связываем первый элемент с p

beg=p;// p становится первым элементом списка

}

return beg;

}

2.3. Очередь и стек

Очередь и стек – это частные случаи однонаправленного списка.

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

  • top() – доступ к вершине стека

  • pop() – удаление элемента из вершины;

  • push() – добавление элемента в вершину.

Такой принцип обслуживания называют LIFO(lastin–firstout, последний пришел, первый ушел).

В очереди добавление осуществляется в один конец, а удаление из другого конца. Такой принцип обслуживания называют FIFO(firstin–firstout, первый пришел, первый ушел). Для очереди также определяют функции:

  • front() – доступ к первому элементу;

  • back() – доступ к последнему элементу;

  • pop() – удаление элемента из конца;

  • push() – добавление элемента в начало.

2.4. Бинарные деревья

Бинарное дерево – это динамическая структура данных, состоящая из узлов, ка­ждый из которых содержит, кроме данных, не более двух ссылок на различные бинарные деревья. На каждый узел имеется ровно одна ссылка.

Описать такую структуру можно следующим образом:

struct point

{

int data;//информационное поле

point *left;//адрес левого поддерева

point *right;//адрес правого поддерева

};

Начальный узел называется корнем дерева. Узел, не имеющий поддеревьев, называется листом. Исходящие узлы называются предками, входящие — потом­ками. Высота дерева определяется количеством уровней, на которых располага­ются его узлы.

Если дерево организовано таким образом, что для каждого узла все ключи его ле­вого поддерева меньше ключа этого узла, а все ключи его правого поддерева — больше, оно называется деревом поиска. Одинаковые ключи не допускаются. В дереве поиска можно найти элемент по ключу, двигаясь от корня и переходя на левое или правое поддерево в зависимости от значения ключа в каждом узле. Такой поиск гораздо эффективнее поиска по списку, поскольку время поиска определяется высотой дерева, а она пропорциональна двоичному логарифму ко­личества узлов.

В идеально сбалансированном дереве количество узлов справа и сле­ва отличается не более чем на единицу.

Линейный список можно представить как вырожденное бинарное дерево, в котором каждый узел имеет не более одной ссылки. Для списка среднее время поиска равно половине длины списка.

Деревья и списки являются рекурсивными структурами, т. к. каждое поддерево также является деревом. Таким образом, дерево можно определить как рекурсивную структуру, в которой каждый элемент является:

  • либо пустой структурой;

  • либо элементом, с которым связано конечное число поддеревьев.

Действия с рекурсивными структурами удобнее всего описываются с помощью рекурсивных алгоритмов.