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

Креневич А.П.,Обвінцев О.В.C в задачах і прикладах

..pdf
Скачиваний:
86
Добавлен:
07.03.2016
Размер:
1.37 Mб
Скачать

Розділ 10. Рекурсивні структури даних

171

p -> next = NULL; if (empty(*pq))

pq -> bg = p; else

pq -> en -> next = p; pq -> en = p;

}

int take(queue *pq){ if (empty(*pq)) {

cout << "Queue is empty\n"; return 0;

}

else { qref p; int n;

p = pq -> bg;

n = pq -> bg -> d;

pq -> bg = pq -> bg -> next;

if (pq -> bg == NULL) pq -> en = NULL; free(p);

return n;

}

}

Програма, що виконує завдання:

#include

<stdlib.h>

#include

<iostream.h>

#include

"queue.h"

void main(){

 

queue q;

// Черга

int n;

 

// Змінна для поточного числа

randomize();

 

init(&q);

// Ініціалізація черги

do {

 

 

//Генерація випадкових чисел у змінну n n = random(100);

//Якщо випадкове число дорівнює нулю, то

//припиняємо додавання елементів до черги if (n == 0) break;

add(&q, n);

}while (1);

//Поки черга залишається непорожньою,

//виводимо елементи черги на екран

172

С у задачах і прикладах

 

while (!empty(q))

cout << take(&q) << " "; cout << "\n";

}

Приклад 10.3. Описати модуль для роботи з деком цілих чисел, у якому реалізувати базові операції роботи з деком. Використовуючи цей модуль, реалізувати задачу: з клавіатури ввести послідовність цілих чисел, що завершується 0. На базі послідовності побудувати динамічну структуру, в якій спочатку йтимуть від'ємні числа, а потім – додатні.

Розв'язок. Модуль для роботи з деком складається з двох файлів – файл заголовків deque.h і файл реалізації deque.cpp.

/* deque.h */

//Вказівник на елемент дека typedef struct delem *dref;

//Елемент дека

struct delem { int d;

dref next, prev;

}; // Дек

typedef struct{ dref bg, en;

} deque;

/* Почати роботу */

extern void init(deque *pd);

//Функція визначення, чи є дек порожнім extern int empty(deque d);

//Додати елемент до початку дека

extern void put_bg(deque *pd, int n); // Взяти елемент з початку дека

extern int get_bg(deque *pd, int *pn);

//Додати елемент до кінця дека extern void put_en(deque *pd, int n);

//Взяти елемент з кінця дека

extern int get_en(deque *pd, int *pn);

Файл реалізації:

/* deque.cpp*/ #include <stdio.h> #include <stdlib.h> #include <iostream.h> #include "deque.h" void init(deque *pd){

pd -> bg = NULL;

Розділ 10. Рекурсивні структури даних

173

pd -> en = NULL;

}

int empty(deque d){ return (d.bg == NULL);

}

void put_bg(deque *pd, int n){ dref p;

p = (dref) malloc(sizeof(struct delem)); p -> d = n;

p -> prev = NULL;

p -> next = pd -> bg;

if (pd -> bg == NULL) pd -> en = p; else pd -> bg -> prev = p;

pd -> bg = p;

}

int get_bg(deque *pd, int *pn) { dref p;

if (empty(*pd)){

cout << "get_bg: Дек порожнiй\n";

// якщо дек порожній, get_bg повертає 0 return 0;

}

p = pd -> bg; *pn = p -> d;

pd -> bg = pd -> bg -> next;

if (pd -> bg == NULL) pd -> en = NULL; else pd -> bg -> prev = NULL;

free(p); return 1;

}

void put_en(deque *pd, int n){ dref p;

p = (dref) malloc(sizeof(struct delem)); p -> d = n;

p -> next = NULL;

p -> prev = pd -> en;

if (empty(*pd)) pd -> bg = p; else pd -> en -> next = p;

pd -> en = p;

}

int get_en(deque *pd, int *pn) { dref p;

if (empty(*pd)){

cout << "get_en: Дек порожнiй\n";

174

С у задачах і прикладах

 

// якщо дек порожній, get_en повертає 0 return 0;

}

p = pd -> en; *pn = p -> d;

pd -> en = pd -> en -> prev;

if (pd -> en == NULL) pd -> bg = NULL; else pd -> en -> next = NULL;

free(p); return 1;

}

Для реалізації завдання потрібно аналізувати введене з клавіатури число: якщо воно від'ємне, то додавати його у початок дека, а якщо додатне – у кінець дека. Отже, програма матиме вигляд:

#include <iostream.h> #include "deque.h" void main(){

deque q; int n; init(&q); do {

cin >> n; if (n == 0)

break;

else if (n < 0)

put_bg(&q, n); // додаємо у початок дека else

put_en(&q, n); // додаємо у кінець дека

} while (1);

while (!empty(q)){ get_bg(&q, &n); cout << n << " ";

}

}

Приклад 10.4. Описати модуль, у якому реалізувати базові операції для роботи з класичним списком.

Розв'язок. Опишемо модуль у складі двох файлів – файл заголовків classlst.h і файл реалізації classlst.cpp.

/* classlst.h */

 

typedef struct lelem *list;

/* Список */

struct lelem {

/* Елемент списку */

int d;

 

list next;

 

};

 

Розділ 10. Рекурсивні структури даних

175

/* Почати роботу */

extern void init(list *pl);

/* Операція визначення, чи порожній список */ extern int empty(list l);

/* Додати елемент у початок списку */ extern void add(list *pl, int n);

/* Голова списку */ extern int head(list l); /* Хвіст списку */

extern list tail(list l);

Файл реалізації

/* classlst.cpp */ #include <stdlib.h> #include "classlst.h" void init(list *pl){

*pl = NULL;

}

int empty(list l){ return l == NULL;

}

void add(list *pl, int n){ list p;

p = (list) malloc(sizeof(struct lelem)); p -> d = n;

p -> next = *pl; *pl = p;

}

int head(list l){ if (!empty(l))

return l -> d; else

return 0;

}

list tail(list l){ if (empty(l))

return NULL; else

return l -> next;

}

Як тестову програму реалізуємо таку задачу. У список записати n випадкових чисел, вивести їх на екран, після чого знищити список.

/* uselst.cpp */ #include <iostream.h> #include <stdlib.h>

176

С у задачах і прикладах

 

#include "classlst.h"

//Заповнення списку n випадковими числами void RandomFillList(list *pl, int n){

randomize();

for (int i = 1; i <= n; i++) add(pl, random(10));

}

//Рекурсивна підпрограма

//виведення списку на екран

void ShowList(list l){ if (!empty(l)){

cout << head(l) << " "; ShowList(tail(l));

}

 

}

 

void main(){

 

list l; int n;

 

init(&l);

// Ініціалізація списку

cout << "n=? "; cin >> n; RandomFillList(&l, n); ShowList(l);

}

Зауваження. Класичний список може одночасно використовуватися кількома динамічними структурами. Саме тому список має існувати до завершення виконання програми. Через це у програмі не описано підпрограму для видалення списку з пам'яті. Якщо ж у цьому стане потреба, то підпрограму видалення списку з пам'яті можна описати так:

// Підпрограма видалення списку з пам'яті void Remove(list *pl){

list p;

while (!empty(*pl)){

p = *pl; *pl = p -> next; free(p);

}

Приклад 10.5. Описати модуль, у якому реалізувати базові операції для роботи зі списком з поточним елементом.

Розв'язок. Опишемо модуль у складі двох файлів – файл заголовків listcur.h і файл реалізації listcur.cpp. У задачі розглядатимемо список цілих чисел.

/* listcur.h */

//Вказівник на елемент списку typedef struct lelem *lref;

//Елемент списку

struct lelem { int d;

Розділ 10. Рекурсивні структури даних

177

lref next;

};

//Список - складається з двох полів:

//beg - вказівник на перший елемент списку

//cur – вказівник на поточний елемент списку typedef struct {

lref beg, cur; } list;

//Почати роботу

extern void init(list *pl);

//Визначення, чи порожній залишок списку extern int emp_end(list l);

//Зробити поточним перший елемент списку extern void first(list *pl);

//Перейти до наступного елемента

extern void next(list *pl);

//Отримати поточний елемент extern int current(list l);

//Вставити новий елемент у список перед поточним extern void insert(list *pl, int n);

//Видалити поточний елемент у списку

extern void del_cur(list *pl);

Файл реалізації

/* listcur.cpp */ #include <iostream.h> #include <stdlib.h> #include "listcur.h" void init(list *pl){

pl -> beg = NULL; pl -> cur = NULL;

}

int emp_end(list l){ return l.cur == NULL;

}

void first(list *pl){

pl -> cur = pl -> beg;

}

void next(list *pl){ if (!emp_end(*pl)){

pl -> cur = pl -> cur -> next;

}

}

int current(list l){ if (!emp_end(l))

178

С у задачах і прикладах

 

return l.cur -> d; else

return 0;

}

//Допоміжна функція, що повертає елемент

//списку, що стоїть перед поточним

lref find_prev(list l){ lref p;

if (l.beg == l.cur) p = NULL; else {

p = l.beg;

while (p -> next != l.cur) p = p -> next;

}

return p;

}

void insert(list *pl, int n){ lref p;

p = (lref) malloc(sizeof(struct lelem)); p -> d = n;

p -> next = pl -> cur; if(pl -> beg == pl -> cur)

pl -> beg = p; else

find_prev(*pl) -> next = p;

}

void del_cur(list *pl){ lref p;

if(pl -> cur == NULL){

cout << "del_cur: список порожній\n";

}

else {

p = pl -> cur;

if (pl -> beg == p)

pl -> beg = pl -> cur -> next; else

find_prev(*pl) -> next = pl -> cur -> next; pl -> cur = pl -> cur -> next;

free(p);

}

}

Приклад 10.6. Описати модуль, у якому реалізувати базові операції для роботи з кільцевим списком.

Розділ 10. Рекурсивні структури даних

179

Розв'язок. Опишемо модуль у складі двох файлів – файл заголовків

rlist.h і файл реалізації rlist.cpp.

 

/* rlist.h */

 

typedef struct relem *rlist;

/* Список */

struct relem {

/* Елемент списку */

int d;

 

rlist next;

 

};

 

// Почати роботу

 

extern void init(rlist *pr);

 

// Довжина списку

 

extern int len(rlist r);

 

//Перейти до наступного елемента extern void next(rlist *pr);

//Поточний елемент

extern int current(rlist r);

//Вставити новий елемент у список перед поточним extern void insert(rlist *pr, int n);

//Видалити поточний елемент у списку

extern void del_cur(rlist *pr);

Файл реалізації:

/* rlist.cpp */ #include <iostream.h> #include <stdlib.h> #include "rlist.h" void init(rlist *pr){

*pr = NULL;

}

int len(rlist r){ int i = 0; rlist p;

p = r;

if (p != NULL) do {

p = p -> next; i++;

} while (p != r); return i;

}

void next(rlist *pr){ if (*pr != NULL)

*pr = (*pr) -> next; else

cout << "next: список порожній\n";

}

180

С у задачах і прикладах

 

int current(rlist r){ if (r != NULL)

return r -> d; else {

cout << "current: список порожній\n"; return 0;

}

}

//Допоміжна підпрограма, що повертає попередній

//елемент у списку

rlist find_prev(rlist r){ rlist p;

if (r == NULL) p = NULL; else {

p = r;

while (p -> next != r) p = p -> next;

}

return p;

}

void insert(rlist *pr, int n){ rlist p;

p = (rlist) malloc(sizeof(struct relem)); p -> d = n;

p -> next = *pr; if(len(*pr) == 0) p -> next = p;

else

find_prev(*pr) -> next = p; *pr = p;

}

void del_cur(rlist *pr){ rlist p;

if(*pr == NULL)

cout << "del_cur: список порожній\n"; else {

p = *pr;

if (len(*pr) == 1) *pr = NULL;

else

find_prev(*pr) -> next = (*pr) -> next; *pr = (*pr) -> next;

free(p);

}

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]