Реализовать стэк с помощью связного списка - C (СИ)
Формулировка задачи:
Необходимо на простом С реализовать структуру данных стэк с помошью связного списка.
Так же реализовать работу с записью\выводом чисел из списка (IN\OUT)
Но это в идеале. А вообще, буду очень благодарен, если просто объясните как на Си шке организовать стэк через двусторонний связный список.
Решение задачи: «Реализовать стэк с помощью связного списка»
textual
Листинг программы
#include "stack.h"
struct Stack
{
struct item *top;
DWORD count;
HANDLE hHeap;
CRITICAL_SECTION sec;
};
struct item
{
PVOID data;
struct item *next;
DWORD tag;
SIZE_T size;
};
BOOL CreateStack(struct Stack **stack)
{
HANDLE hHeap;
hHeap = HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
if (!hHeap)
{
return FALSE;
}
*stack = HeapAlloc(hHeap, 0, sizeof **stack);
if (!*stack)
{
HeapDestroy(hHeap);
return FALSE;
}
(*stack)->hHeap = hHeap;
(*stack)->top = NULL;
(*stack)->count = 0;
InitializeCriticalSection(&(*stack)->sec);
return TRUE;
}
BOOL StackPush(struct Stack **stack, PVOID data, SIZE_T size, DWORD tag)
{
struct item *cr;
EnterCriticalSection(&(*stack)->sec);
cr = HeapAlloc((*stack)->hHeap, 0, sizeof *(*stack)->top);
if (!cr)
{
LeaveCriticalSection(&(*stack)->sec);
return FALSE;
}
cr->data = HeapAlloc((*stack)->hHeap, 0, size);
if (!cr->data)
{
HeapFree((*stack)->hHeap, 0, cr);
LeaveCriticalSection(&(*stack)->sec);
return FALSE;
}
memmove(cr->data, data, size);
cr->size = size;
cr->tag = tag;
cr->next = (*stack)->top;
(*stack)->top = cr;
(*stack)->count++;
LeaveCriticalSection(&(*stack)->sec);
return TRUE;
}
BOOL StackPop(struct Stack **stack, PVOID data, PSIZE_T size, PDWORD tag, void(*pfndel)(PVOID data, DWORD tag, SIZE_T size))
{
struct item *cr;
EnterCriticalSection(&(*stack)->sec);
if (!(*stack)->top)
{
LeaveCriticalSection(&(*stack)->sec);
return FALSE;
}
cr = (*stack)->top->next;
memmove(data, (*stack)->top->data, (*stack)->top->size);
if (size)
{
*size = (*stack)->top->size;
}
if (tag)
{
*tag = (*stack)->top->tag;
}
if (pfndel)
{
(*pfndel)((*stack)->top->data, (*stack)->top->tag, (*stack)->top->size);
}
HeapFree((*stack)->hHeap, 0, (*stack)->top->data);
HeapFree((*stack)->hHeap, 0, (*stack)->top);
(*stack)->top = cr;
(*stack)->count--;
LeaveCriticalSection(&(*stack)->sec);
return TRUE;
}
VOID DestroyStack(struct Stack **stack)
{
HANDLE hHeap;
hHeap = (*stack)->hHeap;
DeleteCriticalSection(&(*stack)->sec);
HeapFree((*stack)->hHeap, 0, *stack);
HeapDestroy(hHeap);
*stack = NULL;
}
DWORD GetStackCountItem(struct Stack **stack)
{
return (*stack)->count;
}
Объяснение кода листинга программы
- Структура
stackсодержит указатель на вершину стека, количество элементов в стеке, handle к куче и критическую секцию для синхронизации доступа к полюtop. - Структура
itemсодержит указатель на следующий элемент в связном списке, указатель на данные, тег и размер данных. - Функция
CreateStackсоздает новый экземпляр стека. Сначала она выделяет память под структуруstackв куче, затем инициализирует поля структуры. Функция возвращаетTRUE, если операция была успешна, иFALSEв противном случае. - Функция
StackPushдобавляет новый элемент в стек. Она выделяет память под новый элемент в куче, копирует данные в новый элемент и добавляет новый элемент в связный список. Функция возвращаетTRUE, если операция была успешна, иFALSEв противном случае. - Функция
StackPopудаляет верхний элемент из стека. Она копирует данные из верхнего элемента в указанный параметрdata, затем удаляет элемент из стека. Функция возвращаетTRUE, если операция была успешна, иFALSEв противном случае. - Функция
DestroyStackуничтожает экземпляр стека. Она освобождает память, выделенную под структуруstack, и уничтожает кучу. - Функция
GetStackCountItemвозвращает текущее количество элементов в стеке. - В связном списке каждый элемент содержит указатель на следующий элемент.
- Для синхронизации доступа к полю
topиспользуется критическая секция. - В стек можно добавлять и удалять элементы только в конце и начале соответственно.