
Стек-вектор
SP - индекс элемента вектора
n - длина вектора
тип stack[n];
В приведенных ниже примерах вершина стека определяет элемент стека, доступный для записи.
// запись в стек
intpush(типel){
if(SP< n){
stack[SP++] = el;
return 1;
} else
return 0;
}
// чтение из стека
intpop(тип *el){
if(SP > 0){
*el = stack[--SP];
} else
return 0;
}
Очередь-вектор
TypeQue[QSIZE];/* очередь */
intj = 0,/* индекс начала очереди */
k = 0,/* индекс конца очереди */
cnt = 0;/* количество запросов, поставленных в очередь */
/* Запись в очередь */
intputQ(Typeel)
{
if(j == k &&cnt)
return -1; /* очередьполна */
Que[k] = el;
k = (k + 1) % QSIZE;
cnt ++;
return 0;
}
/* Чтение из очереди */
intgetQ(Type *el)
{
if(!cnt)
return -1; /* очередьпуста */
*el = Que[j];
j = (j + 1) % QSIZE;
cnt --;
return 0;
}
Стек-список
При отображении стека списком используется линейный односвязный список.
struct Item{
типinfo;
Item * next;
};
Исходное состояние
Item *SP=NULL;
// записьвстек
int push(типel){
Item *tmp = new Item;
if(!tmp) return 0;
temp->info = el;
tmp->next = SP;
SP = tmp;
return 1;
}
// чтениеизстека
int pop(тип *el){
Item *tmp = SP;
if(!tmp) return 0;
SP = SP->next;
*el = tmp->info;
deletetmp;
returntmp;
}
Очередь-список
При отображении стека списком используется линейный односвязный список.
struct Item{
типinfo;
Item * next;
};
Item * first, // начало очереди
*last;// конец очереди
// запись в очередь
intputQ(тип el){
Item *ptr = newItem;
if(!ptr) return -1;
ptr->info = el;
ptr->next = NULL;
if(!first) first = ptr;
else last->next = ptr;
last = prt;
return 0;
}
// чтение из очереди
intgetQ(тип *el){
Item *ptr = first;
if(!first) return -1;
*el = first->info;
first = first->next;
delete(ptr);
if(!first) last = NULL;
return 0;
}
При отображении очереди циклическим односвязным списком достаточно иметь один указатель – на последний элемент очереди (last). Первый элемент очереди (циклического списка) будет определяться ее последним элементом; это означает, что указателем на начало очереди будет являться поле next последнего элемента списка, т.е., last->next.
struct Item{
типinfo;
Item * next;
};
Item*last;// конец очереди
// запись в очередь
intputQ(типel){
Item *ptr = new Item;
if(!ptr) return -1;
ptr->info = el;
if(!last)
ptr->next = ptr;
else{
ptr->next = last->next;
last->next = prt;
}
last = prt;
return 0;
}
//чтениеизочереди
intgetQ(тип *el){
Item *ptr;
if(!last) return -1;
ptr = last->next;
*el = prt->info;
if(last = ptr) /*прочитан последний элемент*/
last = NULL;
else
last->next = ptr->next;
deleteptr;
return 0;
}
Просматриваемаятаблица-вектор
struct Item{
int key;
Type info;
};
constintM = 100; /* максимальный размер таблицы */
Память под такую таблицу может быть выделена и статически, и динамически:
Itemtable[M]; // статическое выделение памяти
Item *table = newItem[M]; // динамическое выделение памяти
Статическая просматриваемая таблица-вектор
Для статической просматриваемой таблицы определена только операция поиска элемента. Реализация алгоритма поиска элемента не вызывает затруднений и может быть такой:
intsearch(int k){
inti;
for(i = 0; i< M && table[i].key != k; i++);
return (i<M ? i : -1);
}
Динамическая просматриваемая таблица-вектор
constintM = 20; // Максимальный размер таблицы
struct Item{
int busy; //полезанятости
int key; //ключ
Type info; // информация
};
Item table[M];
int n = 0; // текущий размер таблицы
/* поиск элемента в таблице */
int search(int k){
inti;
for(i = 0; i< n; i++)
if(table[i].busy && table[i].key == k)
returni; /* элемент найден – он занят и имеет искомый ключ */
return-1; /* элемент не найден */
}
/* удаление элемента */
int del(int k){
int l;
if((l = search(k)) < 0)
return-1; /* указанного элемента в таблице нет */
table[l].busy= 0; /* "удаление" элемента */
return0;
}
/* "сборкамусора" */
int garbage()
{
inti, cur = n;
n = 0;
for(i = 0; i< cur; i++)
if(table[i].busy){ /* элементзанят */
if(i != n) /* элемент должен быть перемещен */
table[n] = table[i]; /* перемещение элемента */
n++;
}
returnn== M ? -1 : 0; /* в таблице нет свободного места */
}
/* включение нового элемента в таблицу */
int insert(int k, Type in){
if(search(k) >= 0)
return -1; /* в таблице есть элемент с заданным ключом */
if(n== M) /* в конце таблицы нет свободной позиции */
if(garbage() < 0) /* "сборка мусора" */
return-2; /* в таблице нет свободной позиции */
/* включение нового элемента в таблицу */
table[n].busy = 1;
table[n].key = k;
table[n++].info = in;
return 0;
}
Просматриваемаятаблица-список
structItem{
int key;
Type info;
structItem *next;
};
/* вставка в начало списка, как стек */
Item *ptab; /* указатель на начало таблицы */
int del1(int k)
{
Item *cur, *prev;
cur = ptab;
/* проверяем, есть ли в таблице элементы */
if(!cur)
return -1; /* таблица пуста – отказ */
/* возможно, требуется удалить первый элемент таблицы */
if(cur->key == k){
/* удаляем первый элемент */
ptab = cur->next;
delete cur;
return 0;
}
/* ищем удаляемый элемент среди других элементов таблицы */
while(cur->next){ /* есть другие элементы */
prev = cur;
cur = cur->next;
if(cur->key == k){
/* нашли элемент, который надо удалить */
prev->next = cur->next;
delete cur;
return 0;
}
}
/* естественный выход из цикла – в таблице нет элемента с ключомk */
return -1;
}
Эту функцию можно сократить за счет использования данных типа "указатель на указатель на ...". Введя такую переменную, мы можем записать в нее адрес указателя на элемент списка, что позволит совместить удаление первого и промежуточных элементов таблицы. Текст функции приводится ниже.
structItem{
intkey;
Type info;
structItem *next;
};
Item *ptab; /* указатель на начало таблицы */
int del2(int k)
{
Item *cur, **pptr;
pptr = &ptab; /* указатель на указатель на первый элемент таблицы */
/* ищем удаляемый элемент среди всех элементов таблицы */
while(*pptr){ /* еще есть элементы */
if((*pptr)->key == k){
/* нашли элемент, который надо удалить */
cur = *pptr; /* указатель на удаляемый элемент */
*pptr = cur->next;
Delete cur;
return 0;
}
/* продвигаемся к следующему элементу таблицы */
pptr = &(*pptr)->next;
}
/* естественный выход из цикла – в таблице нет элемента с ключомk */
return-1;
}