You are on page 1of 15

Доц.

д-р Трајковиќ Владимир за интерна употреба

Алгоритми и структури на податоци


– белешки од предавања –

2. Репрезентација на податочни
структури со помош на низи

2.1 Податочен тип: Низа

Прва податочна структура што ќе биде изучувана е структурата наречена низа. Често
пати низата се поистоветува со последователно множество на мемориски локации,
што претставува реализација на таа податочна структура и (за жал) не мора секогаш
да биде точно.

Низата може да се дефинира како множество на подредени парови (индекс,


вредност), при што за секоe појавување на индекс, постои соодветна вредност
асоцирана за тој индекс. Индексите (особено во реализациите подржани од
програмските јазици) вообичано се последователни цели броеви. Во реализациите на
било кој конкретен компјутер, мора да се дефинира максимален број на овие парови
при декларацијата на низата.

Функциите (операциите) кои можат да работат со низа се:


- креирање на празна низа,
- пребарување на вредност според индекс,
- пребарување на индекс според вредност,
- додавање на нов пар (индекс, вредност) и
- бришење на пар (индекс, вредност).

Иако овие операции делуваат тривијално, може да бидат комплексни, особено ако
сакаме да ја задржиме последователноста на индексите и да ги запазиме граничните
случаи (недозволување на промена или бришење на пар од празна низа и додавање на
нов пар во низа со попoлнет максимален број на парови).

Доколку наместо подредени парови воведеме подредени n+1 торки со n индекси и


вредности добиваме дефиниција за n-димензионални низи. Како пример за
дводимензионална низа често се зема репрезентацијата на матрици.

1
Доц. д-р Трајковиќ Владимир за интерна употреба

2.2 Празни матрици (SPARSE MATRICES)

Матрицата како математички концепт се користи во решавањето на многу проблеми.


Во рамките на овој курс ќе не интересираат можните податочни репрезентации на
овој концепт. Примери за матрици се дадени на слика 2.1.

кол 1 кол 2 кол 3 кол 4 кол 5 кол 6


кол 1 кол 2 кол 3 − 15⎤
ред 1 ⎡ 15 0 0 22 0
⎡- 27 3 4⎤
⎢ 6
⎢ 0 11 3 0 0 0 ⎥⎥
82 − 0.3⎥⎥
ред 2 ⎢
ред 3 ⎢ ⎢ 0 0 0 -6 0 0⎥
⎢109 − 64 4⎥ ⎢ ⎥
ред 4 ⎢ ⎥ ⎢ 0 0 0 0 0 0⎥
⎢ 12 8 9⎥
⎢ 91 0 0 0 0 0⎥
ред 5 ⎢⎣ 3.4 36 27 ⎥⎦ ⎢ ⎥
ред 6 ⎣⎢ 0 0 28 0 0 0 ⎥⎦

а) б)

слика 2.1: Пример матрици

Првата матрица има 5 редици и 3 колони, па согласно тоа е со димензии 5Х3. Во


општ случај матрицата има m редици и n колони, па велиме дека има димензија m X
n. Таквата матрица има mn елементи. Доколку m = n, матрицата се вика квадратна.

Природен начин за репрезентација на матриците се чини е дводимензионална низа на


пример од типот A(1:m, 1:n). Во тој случај со A(i,j) идентификуваме елемент на
матрицата кој се наоѓа во i-тата редица и j-тата колона. Овој елемент може да се најде
со единствена операција.

Доколку се проучи втората матрица од слика 2.1 се увидува дека таа има голем број
нулеви вредности (од 36 елементи само 8 се ненулеви). Ваквите матрици се
нарекуваат празни матрици. Постојат голем број на такви матрици кои доколку се
чуваат на конвенционалниот начин трошат голем мемориски простор. Проблемот
станува уште подрастичен доколку станува збор за матрица со димензија 1000 Х 1000
која има неколку ненулеви вредности. Еден начин за нивна репрезентација е
користење на низа од подредена тројка каде вредностите i и j соодветствуваат на
индексите на оригиналната матрица, додека вредноста value кореспондира со
вредноста на елементот на оригиналната матрицата кој има индекси i и j.

(i,j,value).

При тоа, првата тројка од така дефинираната низа може да ги опише димензиите на
оригиналната матрица и бројот на ненулеви елементи во неа. На тој начин, наместо
да користиме 36 мемориски полиња користиме само 27 мемориски полиња (8х3 за
ненулевите елементи на матрицата и 1х3 за описот на димензиите и бројот на
ненулеви елементи во матрицата).

Овој пристап треба да се користи внимателно. За разлика од програмските


трансформации на матриците репрезентирани на класичен начин, алгоритмите кои

2
Доц. д-р Трајковиќ Владимир за интерна употреба

работат со репрезентацијата на празните матрици знаат да бидат многу


покомплексни.

Понекогаш е потребно информациите од празната матрицата дополнително да се


организираат (на пример да се појавуваат сортирани според редиците па колоните)
или пак на некој друг начин. Тогаш може да се дефинира низа од подредени
четворки, каде што првиот елемент на четворката е едноставно некоја дополнителна
информција - на пример реден број.

Таков пример за втората матрица од слика 2.1 е даден на слика 2.2. Во овој случај се
користат 9х4 = 36 полиња, што е ист број на полиња како на оригиналната матрица.
Дополнително битно е да се напомене дека со математички трансформации од празни
матрици можат да се добијат непразни матрици.

1, 2, 3
------------
A(0, 6, 6, 8)
(1, 1, 1, 15)
(2, 1, 4, 22)
(3, 1, 6, -15)
(4, 2, 2, 11)
(5, 2, 3, 3)
(6, 3, 4, -6)
(7, 5, 1, 91)
(8, 6, 3, 28)

слика 2.2: Пример репрезентација на празна матрица

2.3 Репрезентација на Податочен тип: Подредена листа

Низите (со воведување на дополнителни ограничувања) најчесто се користат за


репрезентација на податочниот тип линеарна (или подредена) листа.

Постојат многу примери за подредени листи:

- денови во неделата: (ПОНЕДЕЛНИК, ВТОРНИК, СРЕДА, ЧЕТВРТОК,


ПЕТОК, САБОТА, НЕДЕЛА)

- вредности на карти (2, 3, 4, 5, 6, 7, 8, 9, 10, џандар, кралица, крал, кец)

Сите тие можат да се генерализираат со (a1,a2,a3, ...,an) каде ai се вредности од


доменот D. Оваа податочна листа има n елементи. Празната или нулева листа има
n=0 елементи.

Постојат множество на операции кои можат да се извршат врз вака дефинираните


листи:

(i) најди ја должината на листата, n;

(ii) измини ја (и прочитај) листата од лево на десно (или од десно на лево);

3
Доц. д-р Трајковиќ Владимир за интерна употреба

(iii) најди го i-тиот елемент, 1 ≤ i ≤ n ;

(iv) смести нова вредност на i-тата позиција (промена на i-тата позиција),


1≤ i ≤ n;

(v) смести нова вредност на i-тата позиција со вметнување 1 ≤ i ≤ n + 1


предизвикувајќи елементите индексирани со i,i + 1, ...,n да бидат индексирани
со i + 1,i + 2, ...,n + 1;

(vi) избриши елемент од i-тата позиција 1 ≤ i ≤ n предизвикувајќи елементите


индексирани со i + 1, ...,n да бидат индексирани со i,i + 1, ...,n - 1.

Како еден типичен пример за користење на податочната структура подредена листа


(во понатамошниот текст листа) често се зема репрезентацијата и манипулацијата со
полиноми. На пример, нека се дадени два полинома:

P1(x) = 3x2 + 2x + 4 и P2(x) = x4 + 10x3 + 3x2 + 1

Која е правата податочна структура со која тие можат да бидат претставени?

Во општ случај полиномот P(x) од степен n се запишува со

P(x) = anxn + an-1xn-1 + ... + a1x + a0

каде an ≠ 0. Со aixi е означен i-тиот коефициент ai кој одговара на експонентот xi.

Една можна репрезентација на тој полином би била листата

P = (n,an ,an-1, ...,a1,a0).

која може да биде претставена со еднодимензионално поле со должина n + 2, каде


што првиот елемент го дава степенот на полиномот по што следат n + 1 коефициенти
во опаѓачки редослед во однос на соодветниот експонент.

Дали постојат недостатоци (слабости) на оваа репрезентација? Да го разгледаме


случајот:

P(x) = x1000 + 1

за репрезентација на овој полином ќе ни биде потребна низа со должина 1002, при


што 999 вредности во таа низа ќе бидат еднакви на нула. Поради тоа, постои потреба
од алтернативни репрезентации на општиот облик на полиномите. Да го разгледаме
повторно општиот облик на полиномот P(x), но овој пат претставен само со
коефициентите кои немаат нулеви вредности. Тогаш имаме:

P(x) = bm-1 xem-1 + bm-2xem-2 + ... + boxeo

4
Доц. д-р Трајковиќ Владимир за интерна употреба

каде секое bi е ненулев коефициент на полиномот, а експонентите ei се во опаѓачки


редослед em −1 > em − 2 > ... > e0 ≥ 0 . Во тој случај полиномот може да се претстави со
низа со должина 2m + 1,

(m,em-1,bm-1,em-2,bm-2, ...,e0,b0)

каде што првиот елемент е бројот на ненулеви коефициенти, а за секој коефициент е


наведен и експонентот за кој тој се однесува.

Иако овој пристап го решава проблемот со x1000 + 1, прилично елегантно со помош на


репрезентацијата (2,1000,1,0,1), алгоритмите кои би овозможиле манипулација
(собирање, множење) со ваква репрезентација на полиноми се релативно посложени
за изведба затоа што мора де се испита секој експонент пред да почне
манипулацијата со коефициентите.

Дополинително примерот, P2(x) = x4 + 10x3 + 3x2 + 1 претставен во двете


репрезентации изгледа

(4,1,10,3,0,1) или (4,4,1,3,10,2,3,0,1).

од што може да заклучиме дека генерално постојат сериозни проблеми при


користењето на низи за репрезентација на податочниот тип листи. Овие проблеми
произлегуваат од последователноста на индексите која имплицитно се подразбира
при користење на низите. Решение на проблемот тогаш очигледно би било
воведување на нов начин на репрезентација на податочната структура која нема да ја
подразбира таа секвенцијалност (неменливост – статичност) со што ќе овозможат
поголема слобода (динамичност) на манипулацијата со податоците.

2.4 Репрезентација на множество подредени листи

Проблемот на репрезентација на подредена листа во најопшт случај опфаќа


репрезентација на множество од m подредени листи со различна должина.

(a11,a12, ...,a1n1), (a2l,a22, ...,a2n2), ...,(am1,am2, ...,amnm)

каде ni, должината на i-тата листа, е цел број поголем или еднаков на нула.

Дводимензионална низа како репрезентација на вакава податочна структура не


претставува најелегантно решение поради потребата од декларација на матрица М со
димензии (m,max{n1, ...,nm}), што може да предизвика големо неискористување на
меморискиот простор.

Алтернативно можно решение би било користење на еднодимензионална низа со


воведување на специјални индекси - покажувачи: front(i) и rear(i) за идентификување
на почетокот и крајот на секоја од i-те листи. Во тој случај потребени се само 2m + n1
+ n2 + ... + nm мемориски локации. Во тој случај, проблем ќе претставува операцијата
внесување на нов елемент во листата i во која не постои достапен слободен простор,
па мораме да ги поместуваме елементите на листата i + 1 (а можеби и листтата i + 2,

5
Доц. д-р Трајковиќ Владимир за интерна употреба

..., листата m) надесно односно листата i-1 (а можеби и листата i-2,..., листата 1) на
лево.

Пример: Нека се дадени A(x) = 2x + 3, B(x) = x2 + 5x + 3, C(x) = 3x10 + 9x4

и редоследот на индекси POLY: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... max

тогаш вредностите на полиномите се дадени со

2.5 Репрезентација на магацини и редови

Магацините и редовите се едни од најчесто користените податочни типови за


потребите на компјутерските алгоритми. Овие податочни типови се специјални
типови на податочниот тип подредена листа.

Магацин (stack) е подредена листа каде сите вметнувања и бришења на елементи се


прават на едниот крај на листата наречен врв (top). Ред (queue) е подредена листа
каде сите вметнувања се прават на крајот на листата (rear), додека сите бришења се
прават на почетокот на листата (front).

слика 2.3 Графичка репрезентација на податочните структури магацин и ред

Од дефиницијата на магацинот произлегува дека елементите кои се први вметнати во


него се бришат последни и обратно. На пример, (види слика 2.3) доколку елементите
A,B,C,D,E се вметнуваат последователно во еден магацин, првиот елемент што ќе
биде изваден од него е елементот E. Од оваа причина магацините се познати како
Last In First Out (LIFO) листи.

Од дефиницијата на редот произлегува дека елементите кои се први вметнати во него


се бришат први и обратно. На пример, доколку елементите A,B,C,D,E се вметнуваат
последователно во еден ред, првиот елемент што ќе биде изваден од него е елементот
А. Од оваа причина редовите се познати како First In First Out (FIFO) листи.

6
Доц. д-р Трајковиќ Владимир за интерна употреба

2.6 Податочна структура: Магацин

Типичен пример за користење на податочната структура магацин е процесирањето на


повиците на подпрограмите (процедурите, функциите) во рамките на некоја
компјутерска програма. Да замислиме ситуација претставена на слика 2.4

| proc MAIN | | proc A1 | | proc A2 | | proc A3 |


| ___ | | ___ | | ___ | | ___ |
| ___ | | ___ | | ___ | | ___ |
| ___ | | ___ | | ___ | | ___ |
| call A1 | | call A2 | | call A3 | | ___ |
| r: | | s: | | t: | | |
| ___ | | ___ | | ___ | | ___ |
| ___ | | ___ | | ___ | | ___ |
| end | | end | | end | | end |

слика 2.4 Секвенца на повици на потпрограми

Главната програма (MAIN) ја повикува подпрограмата А1. По нејзиното извршување,


главната програма мора да продолжи од линијата (адресата) r. Поради тоа, вредноста
на таа адреса мора некаде да се сочува. Потоа подпрограмот А1 го повикува
подпрограмот А2, кој пак го повикува подпрограмот А3. Во овие повици мора да се
сочуваат адресите s и t. Местото каде што се чуваат овие адреси може (и треба) да се
претстави како магацин. Во конкретниот случај тој ќе изгледа:

(q,r,s,t).

Првата вредност, q, е адресата на главниот програм MAIN во оперативниот систем


каде што тој се извршува. Потребата од магацин е очигледна поради тоа што откако
ќе се изврши подпрограмата А3, треба да заврши извршувањето на подпрограмата А2
и тоа почнувајќи од адресата t итн.

Со податочната структура магацин вообичаено се придружуваат следните операции и


функции.

CREATE (S) - креира празен магацин S;

ADD (i,S) - вметнува елемент i на врвот на магацинот S; Оваа операција кај


податочната структура магацин често се запишува како PUSH(i,S)!

DELETE (S) - го брише врвниот елемент од магацинот S;

TOP (S) - го враќа врвниот елемент од магацинот S; Оваа операција по која


следи операцијата DELETE (S) кај податочната структура магацин често се
запишува како i=POP(S)!

ISEMTS (S) - враќа true ако магацинот S е празен и false ако не е;

Магацините можат да се претстават со помош на еднодимензионални низи со


големина n, каде n би бил максималниот број на вредности дозволени во магацинот.

7
Доц. д-р Трајковиќ Владимир за интерна употреба

Со таа низа, во идеален случај би требало да биде придружена вредност top која ќе го
одредува индексот на врвниот елемент на магацинот.

Во квази структурен јазик операциите PUSH и POP на магацинот претставен со низа


можат да се дадат со:

procedure PUSH (item, STACK, n, top)


//vnesuva element vo magacinot STACK so maksimalna golemina n; top e
brojot na elementi momentalno vo magacinot STACK//
if top ≥ n then call STACK_FULL(OVERFLOW)
else begin
top ← top + 1
STACK (top) ← item
end
end ADD

procedure POP (item, STACK, top)


//go otstranuva top elementot od magacinot STACK i go zacuvuva vo item
se dodeka magacinot ne e prazen//
if top ≤ 0 then call STACK_EMPTY (UNDERFLOW)
else begin
item ← STACK (top)
top ← top - 1
end
end DELETE

Кога магацинот е исполнет не може да се додава нов елемент. Таа ситуација се


нарекува преполнување (OVERFLOW). Слично, кога магацинот е празен од него не
може да се извади врвниот елемент. Во тој случај имаме појава нa испразнетост
(UNDERFLOW). Соодветните акции што треба да се преземат зависат од
конкретната апликација и може да варираат од едноставна нотификација на
корисникот до насилен прекин на програмата.

Во програмскиот јазик С, операциите над магацинот можат да се напишат на


следниот начин:

Декларација на структура

typedef struct
{
bilosto info;
}stackrecord;

каде ’bilosto info’ треба да се замени со конкретен податочен тип, како, на пример ’int
info’ или ’char info’, или некоја произволна комплексна структура. На тој начин сите
манипулации со магацинот важат за произволен тип на податок кој се чува во него.
Доколку предходната декларација (согласно дефиницијата на магацинот) се дополни
со информација за индексот на врвот на магацинот се добива конечната структура:

8
Доц. д-р Трајковиќ Владимир за интерна употреба

typedef struct
{
stackrecord stackarray [LIMIT];
int top;
}stack;

Дефинирање на променлива од тип магацин тогаш едноставно се прави со:

stack s;

Основните операции би можеле да се изведат како:

setstack (ps)
/* Go inicijalizira magacinot s da e prazen */
stack *ps;
{
(*ps).top = -1;
}

empty (ps)
/* Vrakja true samo ako magacinot e prazen */
stack *ps;
{
return ((*ps).top == -1);
}

push (pnewrecord,ps)
/* Go vmetnuva zapisot newrecord na vrvot na magacinot s */
stackrecord *pnewrecord,
stack *ps;
{
if ((*ps).top == (LIMIT - 1))
overflow(ps);
else
{
(*ps).top = (*ps).top + 1;
(*ps).stackarray[(*ps).top].info = (*pnewrecord).info;
}
}

pop(ps,pvalue)
/* Ja kopira sodrzinata na top zapisot od magacinot s vo vrednost (value)
i go otstranuva zapisot od magacinot */
stack *ps;
stackrecord *pvalue;
{
if(empty(ps))
underflow(ps);
else
{
(*pvalue).info = (*ps).stackarray[(*ps).top].info;
(*ps).top = (*ps).top - 1;
}
}

9
Доц. д-р Трајковиќ Владимир за интерна употреба

Функциите overflow и underflow информираат за соодветните неможности за


изведување на саканата операција. Доколку наместо произволен тип се одлучиме за
едноставен податочен тип како вредност на инфо полето од магацинот, горните
процедури се поедноставуваат. Читателите на текстот тоа може да го проверат со
самостојна работа.

Треба да се напомене дека во општ случај линијата

(*ps).stackarray[(*ps).top].info = (*pnewrecord).info;

важи само за инфо полиња кои можат да добијат вредност со помош на операторот
’=’. За произволна структура, потребно е доделување на вредност на секое поле од
структурата.

На аудиториските вежби ќе бидат претставени реализации на овие операции кои не


користат покажувачи.

2.7 Податочна структура: Ред

Типичен пример за користење на податочната структура ред е водење на евиденција


на документи кои чекаат да дојдат на ред за печатење. Секој документ претставува
одредена работа (job) за печатарот. При тоа, во општ случај, првиот документ се
печати прв. Илустрација на овој процес е даден на слика 2.5.

front rear
0 0 Inicijalizacija

0 1 Jl Job 1 vleguva Q
0 2 J1 J2 Job 2 vleguva Q
0 3 J1 J2 J3 Job 3 vleguva Q
1 3 J2 J3 Job 1 napusta Q
1 4 J2 J3 J4 Job 4 vleguva Q
2 4 J3 J4 Job 2 napusta Q

слика 2.5 Евиденција на работа на печатар

Со податочната структура ред вообичаено се придружуваат следните операции и


функции.

CREATEQ(Q) - креира празен ред Q;

ADDQ(i,Q) - вметнува елемент i на крајот од редот Q;

DELETEQ(Q) - брише елемент од почетокот на редот Q;

FRONT(Q) - го враќа првиот елемент од редот Q;

ISEMTQ(Q) - враќа true ако редот Q е празен и false ако не е;

10
Доц. д-р Трајковиќ Владимир за интерна употреба

Репрезентацијата на податочната структура ред со помош на низа е покомплицирана


од репрезентацијата на магацин. Освен еднодимензионална низа со големина n,
потребни ни се две варијабли: front и rear.

За потребите на следниот пример да претпоставиме дека вредноста на front е


секогаш за еден помала од вистинскиот индекс на почетокот на редот, додека
вредноста на rear е секогаш еднаква на индексот на последниот елемент во редот.
Тогаш, front = rear ако и само ако нема елементи во редот. Почетна состојба на редот
или празен ред може да дефинира со: front = rear = 0.

Треба да се напомене дека ова е само една можна конвенција за моделирање на


вредностите на променливите front и rear со цел да се опишат различни состојби на
редот.

Во квази структурен јазик операциите ADDQ и DELETEQ на редот претставен со


низа можат да се дадат со:

procedure ADDQ(item, Q, n, rear)


//vmetnuvanje na element vo red pretstaven so Q(l:n)//
if rear = n then call QUEUE_FULL
rear ← rear + 1
Q(rear)← item
end ADDQ

procedure DELETEQ(item, Q, front, rear)


//brisenje na element od redot//
if front = rear then call QUEUE_EMPTY
front ← front + 1
item ← Q(front)
end DELETEQ

Треба да се примети дека QUEUE_FULL во овој случај не мора да значи дека редот
содржи максимален број на елементи. Оваа состојба, согласно горниот алгоритам
може да се постигне и со едноставно поместување на елементите во редот (види
слика 2.5).

Една можна стратегија (која ќе биде дадена на аудиториски вежби) за надминување


на овој проблем е редот секогаш да се држи ’најлево’ можно, односно променливата
front секогаш да ја има вредноста на првиот индекс од низата.

Друг пристап може да симулира низата со димензија n да е кружна и со индекси од 0


до n-1. Кога rear = n - 1, следниот елемент се вметнува во Q(0) доколку тоа место е
празно. Повторно, front = rear ако и само ако редот е празен. Иницијално front = rear
= 1. На слика 2.6 се дадени неколку можни состојби на оваа репрезентација на ред со
помош на низа.

11
Доц. д-р Трајковиќ Владимир за интерна употреба

слика 2.6 Примена на кружна листа за репрезентација на ред

Последниот пристап ги менува и алгоритмите на местата каде што се врши


инкрементација на вредностите за front и rear во смисла на:

if rear = n - 1 then rear ← 0


else rear ← rear + 1.

if front = n - 1 then front ← 0


else front ← front + 1.

т.е.

rear ← (rear + l)mod n и front ← (front + 1)mod n

па имаме

procedure ADDQ(item, Q, n, front, rear)


//Vmetnuva element vo cirkularniot red zacuvan vo Q(0:n - 1);
rear pokazuva na posledniot element, a front e edna pozicija ponazad, ako
se broi spored dvizenjeto na strelkite na casovnikot, od prviot element
vo Q//

rear ← (rear + l)mod n //pomesti go rear kako strelkite na casov.//


if front = rear then call QUEUE-FULL
Q(rear) ← item //vmetnuva nov element//
end ADDQ

procedure DELETEQ(item, Q, n, front, rear)


//go otstranuva front elementot od redot Q(0:n - 1)//

if front = rear then call QUEUE-EMPTY


front ← (front + 1)mod n // pomesti go front kako strel casov.//
item ← Q(front) //go postavuva elementot kaj front od redot//
end DELETEQ

И оваа имплементација (иако со ефикасност еднаква на константа) не е без проблеми.


Се приметува дека сигнализацијата за полн ред во ADDQ се јавува кога front = rear.
Ако се анализира алгоритмот за ADDQ и конвенциите за редот се добива дека кога

12
Доц. д-р Трајковиќ Владимир за интерна употреба

front = rear постои едно слободно место и тоа во Q(rear), затоа што првиот елемент
на редот не е во Q(front) туку е едно место на лево. Но, ако на тоа место внесеме
елемент нема да постои можност да разликуваме кога редот е полн, а кога празен.

Процедурите QUEUE_FULL и QUEUE_EMPTY слично како STACK_FULL и


STACK_EMPTY зависат од конкретната апликација.

Во програмскиот јазик С, операциите над ред можат да се напишат на следниот


начин:

Декларација на структура

typedef struct
{
bilosto info;
}queuerecord;

typedef struct
{
queuerecord queuearray [LIMIT];
int front, rear;
}queue;

queue q;

Коментарите за овие декларации се аналогни со коментарите дадени за реализацијата


на магацин, со дополнение дека, согласно дефиницијата на податочната структура
ред, освен низата во која се сместени елементи од произволен тип се водат две
променливи за почетокот и крајот на редот соодветно.

Доколку се земе дека CREATEQ ги сетира front и rear на минус еден (-1) и дека
Empty ќе врати вредност true кога front = -1 и false во обратен случај, бришењето
може да се даде со следниот код:

remove (pq, pvalue)


/* Go brise front zapisot od redot q i ja kopira negovata sodrzina vo
value */

queue *pq;
queuerecord *pvalue;

{
if(empty(pq))
printf("\n underflow \n");
else
{
(*pvalue).info = (*pq).queuearray[(*pq).front].info;
(*pq).front = (*pq).front + 1;
if((*pq).front == (*pq).rear) /* ako redot e prazen,
inicijaliziraj go */
setqueue(pq);
if((*pq).front > (LIMIT - 1))
(*pq).front = 0;
}
}

13
Доц. д-р Трајковиќ Владимир за интерна употреба

додека вметнувањето на елемент е дадено со:


insert(pnewrecord,pq)
/* Go vmetnuva newrecord kaj krajot (rear) od redot q */

queuerecord *pnewrecord;
queue *pq;

{
if ((*pq).front == -1)
{
(*pq).front = 0;
(*pq).queuearray[0].info = (*pnewrecord).info;
(*pq).rear = 1;
}
else
if((*pq).rear == (*pq).front)
printf("\n overflow \n");
else
{
if((*pq).rear <= (LIMIT - 1))
{
(*pq).queuearray[(*pq).rear].info = (*pnewrecord).info;
(*pq).rear = (*pq).rear + 1;
}
else
{
if((*pq).front == 0)
printf("\n overflow \n");
else
{
/* ima mesto ako se kruzi, zatoa noviot zapis e vmetnat na
pocetokot na vektorot, a rear e postaven na slednata
lokacija */
(*pq).queuearray[0].info = (*pnewrecord).info;
(*pq).rear = 1;
}
}
}
}

2.8 Повеќекратни магацини и редови

Доколку е потребно да се опишат неколку магацини (редови) со помош на низа, од


предходно кажаното може да се дискутира дека користењето на
повеќедимензионални низи не е секогаш најпогодно, особено од аспект на трошење
на мемориски ресурси. Поради тоа, во продолжение накратко ќе бидат дадени
основните идеи кои можат де се применат при репрезентација на повеќекратни
магацини (а со тоа и редови) со помош на еднодимензионална низа.

Доколку е потребно да се претстават само два магацини, имаме релативно едноставен


случај. Врвовите на магацините ќе ги поставиме на различните краеви на низата и
програмски ќе овозможиме тие да растат еден кон друг. На тој начин, едновремено
работиме со два магацина користејќи иста низа (ист мемориски простор). При
претпоставка дека магацините во просек ќе бидат полупразни, постигнуваме

14
Доц. д-р Трајковиќ Владимир за интерна употреба

максимална искористеност на меморискиот простор. Повеќе детали за овој концепт


ќе бидат обработени на аудиториските вежби.

За жал, кога треба да претставиме повеќе (да речеме n) магацини, овој пристап не
може да биде искористен. Еден можен пристап е да ја поделиме иницијално
достапната меморија (големина на низата) на n еднакви делови и да алоцираме по
еден таков сегмент на секој од магацините. За секој магацин i можеме да дефинираме
позиција B(i) која е за едно помала од дното на магацинот. Тогаш T(i), 1 i n, ќе го
одредува врвот на соодветниот магацин i. Граничниот услов B(i) = T(i) ќе укажува на
фактот дека магацинот i е празен. Согласно горе кажаното, почетната поделба (види
слика 2.7) е утврдена со:

B (i) = T (i) = m/n (i - 1), 1 i n

слика 2.7 Иницијална распределба на единствена низа (меморија) помеѓу повеќе


магацини

За овие магацини во поедноставен случај важат скоро истите алгоритми за


операциите PUSH и POP. Интересен е фактот дека со овој пристап овозможуваме
флексибилност на појавата на OVERFLOW. Имено при оваа појава, може да се
испита дали магацините може да се поместат на лево или на десно за да се направи
место за новиот елемент (види слика 2.8). Овој концепт претставува основа на цела
група алгоритми кои работат со управување со меморија и делливи ресурси воопшто
и овозможува поефикасна работа на конкурентни програми (процеси) на еден
компјутер.

слика 2.8 Состојба во која i-тиот магацин е пополнет но може да се избегне негов
OVERFLOW со распределба на ресурсите.

15

You might also like