Professional Documents
Culture Documents
2. Репрезентација на податочни
структури со помош на низи
Прва податочна структура што ќе биде изучувана е структурата наречена низа. Често
пати низата се поистоветува со последователно множество на мемориски локации,
што претставува реализација на таа податочна структура и (за жал) не мора секогаш
да биде точно.
Иако овие операции делуваат тривијално, може да бидат комплексни, особено ако
сакаме да ја задржиме последователноста на индексите и да ги запазиме граничните
случаи (недозволување на промена или бришење на пар од празна низа и додавање на
нов пар во низа со попoлнет максимален број на парови).
1
Доц. д-р Трајковиќ Владимир за интерна употреба
а) б)
Доколку се проучи втората матрица од слика 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)
3
Доц. д-р Трајковиќ Владимир за интерна употреба
P(x) = x1000 + 1
4
Доц. д-р Трајковиќ Владимир за интерна употреба
(m,em-1,bm-1,em-2,bm-2, ...,e0,b0)
каде ni, должината на i-тата листа, е цел број поголем или еднаков на нула.
5
Доц. д-р Трајковиќ Владимир за интерна употреба
..., листата m) надесно односно листата i-1 (а можеби и листата i-2,..., листата 1) на
лево.
6
Доц. д-р Трајковиќ Владимир за интерна употреба
(q,r,s,t).
7
Доц. д-р Трајковиќ Владимир за интерна употреба
Со таа низа, во идеален случај би требало да биде придружена вредност top која ќе го
одредува индексот на врвниот елемент на магацинот.
Декларација на структура
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
Доц. д-р Трајковиќ Владимир за интерна употреба
(*ps).stackarray[(*ps).top].info = (*pnewrecord).info;
важи само за инфо полиња кои можат да добијат вредност со помош на операторот
’=’. За произволна структура, потребно е доделување на вредност на секое поле од
структурата.
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
10
Доц. д-р Трајковиќ Владимир за интерна употреба
Треба да се примети дека QUEUE_FULL во овој случај не мора да значи дека редот
содржи максимален број на елементи. Оваа состојба, согласно горниот алгоритам
може да се постигне и со едноставно поместување на елементите во редот (види
слика 2.5).
11
Доц. д-р Трајковиќ Владимир за интерна употреба
т.е.
па имаме
12
Доц. д-р Трајковиќ Владимир за интерна употреба
front = rear постои едно слободно место и тоа во Q(rear), затоа што првиот елемент
на редот не е во Q(front) туку е едно место на лево. Но, ако на тоа место внесеме
елемент нема да постои можност да разликуваме кога редот е полн, а кога празен.
Декларација на структура
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 во обратен случај, бришењето
може да се даде со следниот код:
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
Доц. д-р Трајковиќ Владимир за интерна употреба
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;
}
}
}
}
14
Доц. д-р Трајковиќ Владимир за интерна употреба
За жал, кога треба да претставиме повеќе (да речеме n) магацини, овој пристап не
може да биде искористен. Еден можен пристап е да ја поделиме иницијално
достапната меморија (големина на низата) на n еднакви делови и да алоцираме по
еден таков сегмент на секој од магацините. За секој магацин i можеме да дефинираме
позиција B(i) која е за едно помала од дното на магацинот. Тогаш T(i), 1 i n, ќе го
одредува врвот на соодветниот магацин i. Граничниот услов B(i) = T(i) ќе укажува на
фактот дека магацинот i е празен. Согласно горе кажаното, почетната поделба (види
слика 2.7) е утврдена со:
слика 2.8 Состојба во која i-тиот магацин е пополнет но може да се избегне негов
OVERFLOW со распределба на ресурсите.
15