Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
4 Курс / Практика / metodichka_u_praktika.doc
Скачиваний:
10
Добавлен:
30.05.2020
Размер:
2.15 Mб
Скачать

Робота №15 Програмування з використанням двусвязанных списків

15.1. Черги на основі двусвязанных списків

Двусвязанний список складається з елементів, що містять заслання як на попередній, так і на подальший елементи. Така організація дозволяє здійснювати переміщення за списком в будь-якому напрямі. Це спрощує роботу із списком, зокрема, вставку і видалення. Також підвищується стійкість роботи, оскільки можна відновити втрачене заслання. Недоліком є введення додаткового покажчика, що декілька ускладнює програму.

Оголошення рекурсивного типа – двусвязанная черга:

struct tochd

{

int inf;

tochd *left;

tochd *rigth;

} *sp;

Створення черги

void NewOchd(tochd **sl, tochd **sr)

{

*sl=new tochd;

*sr=new tochd;

(*sl)->left = NULL;

(*sl)->rigth = *sr;

(*sr)->left = *sl;

(*sr)->rigth = NULL;

return;

}

Підключення

tochd *sl, *sr;

NewOchd(&sl,&sr);

Додавання елементу після заданого

void AddOchdRigth(tochd *sp, int inf)

{

tochd *spt=new tochd;

spt->inf = inf;

spt->left = sp;

spt->rigth = sp->rigth;

sp->rigth = spt;

spt->rigth->left = spt;

return;

}

Додавання елементу перед заданим

void AddOchdLeft(tochd *sp, int inf)

{

tochd *spt=new tochd;

spt->inf = inf;

spt->left = sp->left;

spt->rigth = sp;

spt->left->rigth = spt;

sp->left = spt;

return;

}

Читання і видалення елементу з адресою sp

int ReadOchdD(tochd *sp)

{

int inf= sp->inf;

sp->left->rigth = sp->rigth;

sp->rigth->left = sp->left;

delete sp;

return inf;

}

Видалення всієї черги

void DelOchdAll(tochd **sl, tochd **sr)

{

tochd *spt = (*sl)->rigth;

while(spt != *sr)

{

cout << ReadOchdD(spt) << endl;

spt = (*sl)->rigth;

}

delete *sl; *sl = NULL;

delete *sr; *sr = NULL;

return;

}

Сортування злиттям

Розбиття списку на 2 списки

void div2Ochd(tochd *sl, tochd *sr,tochd **slL,

tochd **srL,tochd **slR, tochd **srR)

{

NewOchd(slL,srL);

NewOchd(slR,srR);

tochd *spt = sl->rigth;

while(spt != sr)

{

AddOchdLeft(*srL, ReadOchdD(spt));

spt = sl->rigth;

if (spt != sr)

{

AddOchdLeft(*srR, ReadOchdD(spt));

spt = sl->rigth;

}

}

delete sl;

delete sr;

}

Злиття двох відсортованих списків

void slipOchd(tochd **sl, tochd **sr,tochd *slL, tochd *srL,tochd *slR, tochd *srR)

{

NewOchd(sl,sr);

tochd *sptL = slL->rigth;

tochd *sptR = slR->rigth;

while ((sptL != srL) && (sptR != srR))

{

if (sptL->inf < sptR->inf)

{

AddOchdLeft(*sr, ReadOchdD(sptL));

sptL = slL->rigth;

}

else

{

AddOchdLeft(*sr, ReadOchdD(sptR));

sptR = slR->rigth;

}

}

while (sptL != srL)

{

AddOchdLeft(*sr, ReadOchdD(sptL));

sptL = slL->rigth;

}

delete slL; delete srL;

while (sptR != srR)

{

AddOchdLeft(*sr, ReadOchdD(sptR));

sptR = slR->rigth;

}

delete slR; delete srR;

}

Сортування

void SotrSlipOchd(tochd **sl, tochd **sr)

{

tochd *slL, *srL,*slR, *srR;

if ((*sl)->rigth->rigth == *sr) return;

div2Ochd(*sl,*sr,&slL,&srL,&slR,&srR);

SotrSlipOchd(&slL,&srL);

SotrSlipOchd(&slR,&srR);

slipOchd(sl,sr,slL,srL,slR,srR);

}

15.2. Індивідуальні завдання

Створити двонаправлений список з числами в діапазоні від –50 до +50. Після створення списку виконати індивідуальне завдання і вивести результат. Написати програму сортування і пошуку в двонаправленому списку. Відсортувати список і вивести його на екран. Знайти елемент списку, рівний номеру варіанту, і вивести його порядковий номер або повідомлення про те, що такого елементу немає. В кінці роботи всі списки мають бути видалені.

1. Знайти мінімальний елемент і зробити його першим.

2. Створити два списки. Перший повинен містити лише позитивні, а другий – лише негативні числа.

3. Видалити із списку всі елементи, що знаходяться між його максимальним і мінімальним значеннями.

4. Перемістити в другий список всі елементи, що знаходяться після елементу з максимальним значенням.

5. Змістити по кільцю елементи списку на задане число позицій.

6. Видалити всі негативні елементи списку.

7. З елементів, розташованих між максимальним і мінімальним елементами, створити кільце. Останні елементи повинні залишитися в першому списку.

8. Видалити перший і останній елементи списку.

9. Видалити по одному елементу справа і зліва від мінімального елементу. Якщо елементи справа або зліва відсутні, то видалити сам мінімальний елемент.

10. Видалити елементи, ув'язнені між максимальним і мінімальним значеннями.

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

12. Поміняти місцями елементи з максимальним і мінімальним значеннями, при цьому елементи не повинні переміщатися в пам'яті.

13. Перетворити список в кільце. Передбачити можливість руху по кільцю в обоє сторони з відображенням місця положення поточного елементу. В кінці роботи відновити початковий список.

14. Поміняти місцями перший і максимальний елементи списку.

15. Поміняти місцями перший і останній елементи списку.

Робота №16

Програмування з використанням деревовидних структур даних

16.1. Основні операції з бінарним деревом пошуку

Оголошена структура наступного типа:

struct ttree

{

int inf;

ttree *left;

ttree *rigth;

} *proot;

Додавання нового елементу

ttree *addtree(ttree *proot, int inf)

{

ttree *nl, *pr, *ps;

bool b;

nl = new ttree;

nl->inf = inf;

nl->left = NULL;

nl->rigth = NULL;

if (proot == NULL) return nl;

ps = proot;

while (ps != NULL)

{

pr=ps;

b = (inf < ps->inf);

if (b) ps = ps->left;

else ps = ps->rigth;

}

if (b) pr->left = nl;

else pr->rigth = nl;

return proot;

}

Обхід всього дерева

void wrtree(ttree *p)

{

if (p==NULL) return;

wrtree(p->left);

cout << p->inf << " ";

wrtree(p->rigth);

}

Пошук елементу із заданим ключем

void poisktree(ttree *p,int key, bool &b, int &inf)

{

if ((p != NULL) && (b != true))

{

if (p->inf !=key)

{

poisktree(p->left, key,b,inf);

poisktree(p->rigth,key,b,inf);

}

else {

b=true;

inf=p->inf;

}

}

return;

}

Пошук елементу з максимальним ключем

int poiskmaxtree(ttree *p)

{

while (p->rigth != NULL) p = p->rigth;

return p->inf;

}

Видалення всього дерева

ttree *deltree(ttree *p)

{

if (p==NULL) return NULL;

deltree(p->left);

deltree(p->rigth);

delete(p);

p = NULL;

return NULL;

}

Видалення елементу із заданим ключем

ttree *dellist(ttree *proot, int inf)

{

ttree *ps = proot *pr = proot *w, *v;

// Пошук вузла, що видаляється

while ((ps != NULL) && (ps->inf != inf))

{

pr = ps;

if (inf < ps->inf) ps = ps->left;

else ps = ps->rigth;

}

if (ps == NULL) return proot; // Якщо вузол не знайдений

// Якщо вузол не має дочок

if ((ps->left == NULL) && (ps->rigth == NULL))

{

if (ps == pr) // Якщо це був останній елемент

{

delete(ps);

return NULL;

}

if (pr->left == ps) // Якщо вузол, що видаляється, зліва

pr->left = NULL;

else // Якщо вузол, що видаляється, справа

pr->rigth = NULL;

delete(ps);

return proot;

}

// Якщо вузол має дочку лише справа

if (ps->left == NULL)

{

if (ps == pr) // Якщо віддаляється корінь

{

ps = ps->rigth;

delete(pr);

return ps;

}

if (pr->left == ps) // Якщо вузол, що видаляється, зліва

pr->left = ps->rigth;

else // Якщо вузол спава, що видаляється

pr->rigth = ps->rigth;

delete(ps);

return proot;

}

// Якщо вузол має дочку лише зліва

if (ps->rigth == NULL)

{

if (ps == pr) // Якщо віддаляється корінь

{

ps = ps->left;

delete(pr);

return ps;

}

if (pr->left == ps) // Якщо вузол, що видаляється, зліва

pr->left = ps->left;

else // Якщо вузол спава, що видаляється

pr->rigth = ps->left;

delete(ps);

return proot;

}

// Якщо вузол має двох дочок

w = ps->left;

if (w->rigth == NULL) // Якщо максимальний слідує за ps

w->rigth = ps->rigth;

else // Якщо максимальний не слідує за ps

{

while (w->rigth != NULL)

{

v = w;

w = w->rigth;

}

v->rigth = w->left;

w->left = ps->left;

w->rigth = ps->rigth;

}

if (ps == pr) // Якщо віддаляється корінь

{

delete(ps);

return w;

}

if (pr->left == ps) // Якщо вузол, що видаляється, зліва

pr->left = w;

else // Якщо вузол, що видаляється, справа

pr->rigth = w;

delete(ps);

return proot;

}

16.2. Індивідуальні завдання

Створити збалансоване дерево пошуку з числами в діапазоні від –50 до +50 і роздрукувати інформацію прямим, зворотним обходом і в порядку зростання. Написати функції додавання нового значення, видалення значення, пошуку значення. Виконати індивідуальне завдання і вивести результат. Вся виділена пам'ять має бути звільнена.

1. Поміняти місцями інформацію, що містить максимальний і мінімальний ключі.

2. Підрахувати число листя в дереві (Аркуш – це вузол, з якого немає заслань на інші вузли дерева).

3. Видалити з дерева гілку з вершиною, що має заданий ключ.

4. Визначити максимальну глибину дерева, тобто число вузлів в щонайдовшій дорозі від кореня дерева до листя.

5. Визначити число вузлів на кожному рівні дерева.

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

7. Визначити кількість символів у всіх рядках, що знаходяться у вузлах дерева.

8. Визначити число листя на кожному рівні дерева.

9. Визначити число вузлів в дереві, в яких є покажчик лише на одну гілку.

10. Визначити число вузлів в дереві, в яких є дві дочки.

11. Визначити кількість записів в дереві, що починаються з певної букви (наприклад «a»).

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

13. Знайти запис з ключем, найближчим до середнього значення між максимальним і мінімальним значеннями ключів.

14. Визначити кількість вузлів в лівій гілці дерева.

15. Визначити кількість вузлів в правій гілці дерева.