Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lexzii_08 / lexs_12_obekt.doc
Скачиваний:
27
Добавлен:
17.05.2015
Размер:
194 Кб
Скачать
☆

Ел-т 1

Ел-т 2

Ел-т N

NULL

…

Це простий однонаправлений список, в якому кожен елемент (крім останнього) має посилання на наступний елемент і поле інформації. Можна створити також кільцевий список (в ньому останній елемент буде містити посилання на перший) або двонаправлений список ( коли кожен елемент, крім першого і останнього, має два посилання: на попередній і наступний елемент) і т.д. Крім того, можна розташувати в початок списку додатковий елемент, який називаєтьсязаголовком списку.Як правило, заголовок списку використовується для зберігання інформації про увесь список. Зокрема він може містити лічильник кількості елементів в списку. Наявність заголовку приводить до ускладнення одних і спрощення інших програм, які працюють зі списками (див. малюнок).

Ел-т 1

NULL

Ел-т 2

Ел-т N

NULL

…

При роботі зі спискомможуть бути корисними наступні базові функції:

insert() – добавити новий елемент в список так, щоб список залишився впорядкованим по збільшенню значення одного із полів;

take out() – вилучити елемент із заданим полем(якщо він є в списку);

is_present() –визначити, чи є в списку заданий елемент;

display( ) – роздрукувати значення всіх елементів у списку;

destroy_list– вивільнити пам’ять, яку займає список;

Достатньо часто при роботі з даними буває зручно використовувати структури з неієрархічним зображенням, які добре відображаються за допомогою дерева

Дерево складається з елементів, які називаються вузлами (вершинами). Вузли з’єднуються між собою направленими дугами. У випадку Х->Y вершина Х називаєтьсяпопередником (родичем, батьком), а Y –спадкоємцем(сином). Дерево має один вузол – корінь, у якого немаєпопередника. Будь-який інший вузол має рівно одногопопередника. Вузол, який не маєспадкоємця, називається листом.

Розглянемо роботу з бінарним деревом (в якому у кожного вузла може бути тільки два спадкоємця – лівий і правий син).

Необхідно вміти: - побудувати дерево;

  • виконати пошук елемента з указаним значенням у вузлі;

  • вилучити заданий елемент;

  • обійти всі елементи дерева (наприклад, щоб над кожним із них провести деяку операцію).

Зазвичай бінарне дерево будується одразу впорядкованим, тобто вузол лівого сина має значення менше, ніж значення батька, а вузол правого сина – більше. Наприклад, якщо надходять числа 17, 18, 6, 5, 9, 23, 12, 7,8, то побудоване по ним дерево буде мати такий вигляд:

17

  1. 18

  1. 923

  1. 12

8

Для того, щоб вставити новий елемент в дерево, потрібно знайти для нього місце. Для цього, починаючи з кореня, будемо порівнювати значення вузлів (Y) зі значенням нового елемента (NEW). Якщо NEW>Y,то підемо по лівій гілці; в противному випадку – по правій. Коли дойдемо до вузла, з якого не виходить потрібна гілка для поданого пошуку, це означає, що місце під новий елемент знайдено.

Шлях пошуку місця для числа 11 в побудованому вище дереві показаний на малюнку.

17

618

5 923

  1. 12

11

При вилученні елемента з дерева, можливі три ситуації:

а) вузол, що вилучається – лист (в цьому випадку потрібно просто вилучити посилання на цей вузол);

б) із вузла, що вилучається виходить тільки одна гілка;

в) із вузла, що вилучається виходять дві гілки (в цьому випадку на місце вузла, що вилучається, потрібно поставити або самий правий вузол лівої гілки, або самий лівий вузол правої гілки для збереження впорядкованості дерева).

Наприклад, побудоване раніше дерево після вилучення вузла 6 може стати таким (див. малюнок):

17

7 18

5 9 23

8 12

11

Розглянемо задачу обходу дерева. Використовують три способи обходу дерева:

  1. Обхід зліва направо: А,R,B(спочатку відвідуємо ліве піддерево, а потім – корінь і, під кінець, праве піддерево;

  2. Обхід зверху вниз: R,A,B(відвідуємо корінь до піддерев);

  3. Обхід знизу вверх: A,B,R(відвідуємо корінь після піддерев).

Цікаво прослідкувати результати цих трьох обходів на прикладі запису формул у вигляді дерева.

Наприклад, формула

(a+b/c)*(d-e*f)

буде виглядати так:

Дерево формується по принципу: операція – вузол, оператори –піддерева.

Обхід 1 дає звичайний інфіксний запис виразу (правда, без дужок).

Обхід 2 – префіксний запис +*a/b*c-d*c*f

Обхід 3 – постфіксний запис (ПОЛИЗ – польська інверсний запис):

fbc/+dcf*-*.

В якості прикладу роботи з деревовидною структурою даних розглянемо вирішення такої задачі.

Вводяться прізвища абітурїєнтів; необхідно роздрукувати їх в алфавітному порядку з вказанням кількості повторів кожного прізвища.

В програмі буде використана рекурсивна функція der(), яка будує дерево прізвищ, а також рекурсивна функція для друку дереваprint_der(), в якій реалізований перший спосіб обходу дерева

#include <alloc.h>

#include<stdio.h>

#define TREE struct der

TREE

{char *w;

int c;

TREE *l;

TREE *r;

}

TREE *der (TREE *kr, char *word)

{ int sr;

if (kr==NULL)

{ kr =(TREE *) malloc (sizeof(TREE));

kr->w=word; kr ->c=1;

kr->=kr->r=NULL;

}

else if ((sr=strcmp(word, kr->w))==) kr->c++;

else if (sr<0) kr->l =der (kr->l, word);

else kr->r=der(kr->r, word);

return kr;

}

void print_der(TREE*kr)

{

if(kr)

{print_der (kr->l);

printf(“слово =%-20s\tколичество повторов - %d\n”,kr->w,kr->c);

print_der(kr->r);

}

}

void main()

{ int i;

TREE *kr;

static char word[40][21];

kr=NULL; i=0;

puts (“введите <40 файлы длиной <20 “);

scanf (“%s”, word[i]);

while (word[i][0]!=’\0’)

{kr=der(kr,word[i]);

scanf (“%s”, word[++i]);

}

print_der(kr);

}

Соседние файлы в папке lexzii_08