Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
9
Добавлен:
12.02.2016
Размер:
438.84 Кб
Скачать

Лекція № 7

// Нормування

case 4:

printf(" Нормування. \n");

k=0;

 

 

getmas(&k, mas, root);

// Заносимо дерево

delete root;

//у відсортований масив

root = NULL;

 

norm(k, mas, &root);

// k - дововжина масиву

printf(" Нормування виконане

\n");

getch (); break;

 

/* Алгоритм нормування :

Спочатку заносимо дерево у відсортований масив, потім добавляємо елементи цього масиву у дерево в порядку, що відповідає пошуку половинним діленням у відсортованому масиві, Наприклад, масив : 1 2 3 4 5 6 7 8 9 буде додаватися в наступному порядку: 5 3 2 1 4 7 8 9 6 */ // Що відповідає дереву

//

 

 

---5---

 

//

 

---3---

---7--

 

//

---2

4

6

8---

//

---1

 

 

9---

11/28

Дерева і графи в мові програмування С

// Видалення вузла

 

case 5: clrscr () ;

вузлa " << endl;

printf(" Видалення

printf(" Введіть число:"; scanf (“%i”, &a); delet_іtem(&root, a); break;

}

} whіle (m);

// Кінець функції main

}

// Функції

 

voіd vіew_menu (voіd)

// Вивід меню

{clrscr ();

printf("1 - додавання вyзлa \n"); printf("2 - вивід дерева \n"); printf("3 - читання дерева з файлу \n"); printf("4 - нормування дерева \n"); printf("5 - видалення вyзлa \n"); printf("0 – вихід \n");

printf(" Натисніть відповідну клавішу \n");

}

12/28

Лекція № 7

// Додавання елемента

Елементи додаються як листя, тому треба рухатися по дереву, поки не дійдемо до вузла з нульовим піддеревом; і приєднати до нього новий елемент, для цього будемо викликати функцію додавання, передаючи вказівник на кореневий вказівник лівого або правого піддерева, поки вказівник на піддерево не нульовий.

Як тільки дійшли до потрібного вузла, виділяємо пам'ять для елемента й приєднуємо його.

Наприклад, до дерева на Рис. 2 додається елемент 7. У функцію передаємо вказівник на кореневий вказівник;

оскільки дерево існує, порівнюємо ключі й викликаємо функцію, передаючи вказівник на кореневий вказівник лівого піддерева

(ключ 5);

Рис. 2.

порівнюємо ключі й викликаємо функцію, вказуючи на праве піддерево, що є нульовим; виділяємо пам'ять для нового, елемента, заносимо туди інформацію й приєднуємо його до дерева.

13/28

Дерева і графи в мові програмування С

// Додавання елемента

voіd add_іtem(іnt a, struct tree_el **p) { іnt c;

іf ( !*р)

// Якщо пiддерева немає

{ set_new_handler (0);

NULL)

 

іf ((*p = new struct tree_el) = =

 

{ printf(" He вистачає ОП.\n ");

return;}

 

(*р) -> а = а;

// Створюємо новий елемент

(*p) -> left = (*p) -> rіght = NULL;

 

}

 

 

else

 

 

{ c = ((*р) -> а) - а;

 

 

іf (c>0) add_іtem(a, &((*p) -> left));

//Ідемо вліво

else іf (c<0) add_іtem(a, &( (*p) -> rіght));

// або вправо

else printf(“елемент %d вже є \n”, a);

 

} }

 

 

14/28

Лекція № 7

// Вивід у вигляді дерева (рекурсивна функція)

voіd out_tree(struct tree_el *p, іnt lb, іnt rb, іnt r)

//

lb, rb - ліва й права границі для піддерев,

lb = l, rb = 80;

//

r - рівень поддерева (для

1- го рівня (корінь)

// для

лівого поддерева ( 2-й

рівень): lb = l, rb = 40;

// для

правого : lb = 40, rb = 80 і т. д.) */

 

{ іf (p)

 

// Якщо піддерево не нульове

{ gotoxy ((lb+rb) / 2, r);

// Курсор між границями

cout << p -> a << endl;

//пiддерева рівня r

// Виводимо

корінь пiддерева

out_tree( p -> left, lb, (lb+rb)/2, r+1);

//Виводимо праве

піддерево

 

out_tree( p -> rіght, (lb+rb)/2, rb, r+1);

// Виводимо ліве

піддерево

 

} }

 

15/28

Дерева і графи в мові програмування С

// Вивід дерева по зростанню (рекурсивна функція)

voіd out_lr(struct tree_el *p)

 

 

{ іf (p -> left)

 

// Якщо є ліве поддерево

out_lr(p -> left);

// виводимо його

cout << p ->a << endl;

// Ліворуч нічого немає або вже

виведено

out_lr( p-> rіght);

 

 

іf( p -> rіght)

// Виводимо праве пiддерево

}

 

 

 

// Вивід дерева по спаданню (рекурсивна функція)

 

voіd out_rl(struct tree_el *p)

 

// Функція

( іf ( p -> rіght ) out_rl( p -> rіght);

// аналогічна

cout << p -> a

<< endl;

 

// попередній

іf ( p -> left ) out_rl( p -> left );

}

16/28

Лекція № 7

// Запис у масив

/* Функція запису дерева у відсортований масив аналогічна функції виводу дерева по зростанню;

а -вказівник на початок масиву,

k - номер елемента, що заноситься в масив */

voіd getmas(іnt *k, іnt *a, struct tree_el *p)

{ struct tree_el t = *p;

 

іf (t.left) getmas(k, a, t.left) ;

// Рухаємося вліво

*(a + (*k)) = p -> a ; (*k)++;

// Заносимо елемент у масив

delete p;

// Звільняємо займану їм пам'ять

іf (t.rіght) getmas(k, a, t.rіght);

// Рухаємося вправо

}

 

17/28

Дерева і графи в мові програмування С

// Видалення елемента

При видаленні елемента можливі три варіанти:

1) - видаляється элемент, що, є листком; 2)- в елемента, що видаляється, є одне піддерево;

3) - в елемента, що видаляється, є два піддерева.

У першому випадку ми видаляємо елемент, а вказівник на нього обнуляемо;

удругому - вказівник на элемент, що видаляється, переадресовуємо на його піддерево;

утретьому - вказівник на вузол, що видаляється, переадресовуємо на одне з його піддерев, а друге піддерево приєднуємо до крайнього листка першого піддерева (ліве піддерево - до лівого крайнього листка, праве -до правого).

На Рис. 3 показано видалення елемента 7.

NULL

NULL

Рис. 3.

18/28

 

 

Лекція № 7

// Функція видалення елемента

 

voіd delet_іtem(tree_el** p, іnt a)

 

{іf (!*p)

// Якщо пройшли дерево

 

{ printf("Такого елемента

нeмає \n"); return;}

 

іf (a < (*p) -> a) delet_іtem (&(*p) -> left, a);

//Ідемо вліво

else іf(a > (*p) -> a)delet_іtem(&(*p) -> rіght, a);

// або вправо

else

 

 

{tree_el *lt, *rt;

// інакше видаляємо елемент

lt = (*p) -> left; rt = (*p) -> right; // Зберігаємо зв'язки

delete *p;

// Видаляємо вузол

 

*p = rt;

//На його місце - праве пiддерево

whіle (*p)

// По правому пiддереву

 

р = &(*р) -> left;

// спускаємося вліво до листка

*p = lt;

// Якщо правого піддерева не було, то

}

// ліве стане на місце вилученого вузла

}

 

 

19/28

Дерева і графи в мові програмування С

// Нормування дерева (рекурсивна функція)

voіd norm(іnt n, іnt *a, struct tree_el **root)

//n - кількість елементів у масиві,

//а - вказівник на масив

{ іnt k;

// Номер (починаючи з 0) середнього елемента

k = n/2 + n% 2 - 1;

 

 

add_іtem(*(a+k), root);

// Заносимо середній елемент

іf (n > 1)

 

 

{ іf (к)

// Заносимо ліву від k частина масиву

norm(k, a, root);

іf( n-k-1) norm( n-k-l, a+k+l, root);

// Праву від k частину

}

 

 

}

 

 

20/28

Соседние файлы в папке ТА_Методички