Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Fundamental Linear Data Structures: Arrays, Linked Lists, Stacks, and Queues

Tech 1

Data structures organize and store data in specific arrangements defining the relationships between elements. Linear structures establish a one-to-one sequential relationship among elements, encompassing arrays, linked lists, stacks, and queues.

Arrays

An array allocates a contiguous block of memory to hold a collection of identical data types. Elements are retrieved using zero-based indexing.

c #include <stdio.h>

#define CAPACITY 5

int main() { int values[CAPACITY] = {10, 20, 30, 40, 50};

printf("First item: %d\n", values[0]);
printf("Third item: %d\n", values[2]);

values[1] = 99;
printf("Modified contents: ");
for (int idx = 0; idx < CAPACITY; idx++) {
    printf("%d ", values[idx]);
}
puts("");
return 0;

}

Advantages

  • Constant time O(1) element lookup due to contiguous allocation.
  • Straightforward implementation.

Disadvantages

  • Static capacity requires predetermined sizing.
  • Slow O(n) modifications (insertions/deletions) due to element shifting.

Use Cases

Situations demanding high-frequency lookups with minimal structural modifications and predictable memory requirements.

Linked Lists

Linked lists consist of independent nodes scattered in memory. Each node encapsulates a payload and a reference (pointer) to the subsequent node. Variations include singly, doubly, and circular configurations.

c #include <stdio.h> #include <stdlib.h>

typedef struct ListItem { int value; struct ListItem* nextPtr; } ListItem;

ListItem* construct_item(int val) { ListItem* freshItem = (ListItem*)malloc(sizeof(ListItem)); freshItem->value = val; freshItem->nextPtr = NULL; return freshItem; }

void attach_end(ListItem** headRef, int val) { ListItem* freshItem = construct_item(val); if (*headRef == NULL) { headRef = freshItem; return; } ListItem current = *headRef; while (current->nextPtr != NULL) { current = current->nextPtr; } current->nextPtr = freshItem; }

void display(ListItem* node) { while (node != NULL) { printf("[%d] -> ", node->value); node = node->nextPtr; } printf("END\n"); }

void cleanup(ListItem* node) { ListItem* temp; while (node != NULL) { temp = node; node = node->nextPtr; free(temp); } }

int main() { ListItem* start = NULL; attach_end(&start, 5); attach_end(&start, 10); attach_end(&start, 15); display(start); cleanup(start); return 0; }

Advantages

  • Elastic sizing allows runtime memory allocation.
  • Rapid O(1) ensertions and deletions by merely redirecting pointers.

Disadvantages

  • Sequential O(n) traversal required for element access.
  • Memory overhead from storing pointer references alongside data.

Use Cases

Environments with unpredictable data volumes, frequent structural alterations, and where direct indexing is unnecessary.

Stacks

A stack enforces a Last-In-First-Out (LIFO) discipline. Modifications are strictly restricted to the top extremity of the structure.

c #include <stdio.h> #include <stdlib.h>

#define LIMIT 100

typedef struct { int buffer[LIMIT]; int topPos; } LifoStack;

void initialize(LifoStack* s) { s->topPos = -1; }

int check_empty(LifoStack* s) { return s->topPos == -1; }

int check_full(LifoStack* s) { return s->topPos == LIMIT - 1; }

void insert(LifoStack* s, int val) { if (check_full(s)) { printf("Stack limit reached\n"); return; } s->buffer[++s->topPos] = val; }

int remove_top(LifoStack* s) { if (check_empty(s)) { printf("Stack is vacant\n"); return -1; } return s->buffer[s->topPos--]; }

int view_top(LifoStack* s) { if (check_empty(s)) { printf("No items in stack\n"); return -1; } return s->buffer[s->topPos]; }

int main() { LifoStack myStack; initialize(&myStack);

insert(&myStack, 100);
insert(&myStack, 200);
insert(&myStack, 300);

printf("Top value: %d\n", view_top(&myStack));
printf("Removed: %d\n", remove_top(&myStack));
printf("New Top: %d\n", view_top(&myStack));

return 0;

}

Advantages

  • Uncomplicated operational logic confined to a single endpoint.
  • Automated memory administration in typical implementations.

Disadvantages

  • Prone to overflow if capacity bounds are exceeded.
  • Inaccessible internal elements without popping upper layers.

Use Cases

Depth-first traversal algorithms, postfix expression evaluation, syntax validation (bracket pairing), undo mechanisms, and navigation history.

Queues

A queue operates on a First-In-First-Out (FIFO) principle. Elements enter at the rear and exit from the front.

c #include <stdio.h> #include <stdlib.h>

#define MAX_BOUND 100

typedef struct { int storage[MAX_BOUND]; int frontIdx; int backIdx; int count; } FifoQueue;

void setup(FifoQueue* q) { q->frontIdx = 0; q->backIdx = -1; q->count = 0; }

int queue_empty(FifoQueue* q) { return q->count == 0; }

int queue_full(FifoQueue* q) { return q->count == MAX_BOUND; }

void add_item(FifoQueue* q, int val) { if (queue_full(q)) { printf("Queue capacity exceeded\n"); return; } q->backIdx = (q->backIdx + 1) % MAX_BOUND; q->storage[q->backIdx] = val; q->count++; }

int remove_item(FifoQueue* q) { if (queue_empty(q)) { printf("Queue has no elements\n"); return -1; } int frontVal = q->storage[q->frontIdx]; q->frontIdx = (q->frontIdx + 1) % MAX_BOUND; q->count--; return frontVal; }

int view_front(FifoQueue* q) { if (queue_empty(q)) { printf("Queue is vacant\n"); return -1; } return q->storage[q->frontIdx]; }

int main() { FifoQueue myQueue; setup(&myQueue);

add_item(&myQueue, 11);
add_item(&myQueue, 22);
add_item(&myQueue, 33);

printf("Head value: %d\n", view_front(&myQueue));
printf("Extracted: %d\n", remove_item(&myQueue));
printf("New Head: %d\n", view_front(&myQueue));

return 0;

}

Advantages

  • Guarantees sequential processing aligning with arrival time.
  • Straightforward design focused on two endpoints.
  • Adaptable resource handling.

Disadvantages

  • Rigid capacity limits risk overflow conditions.
  • Internal elements cannot be queried directly.

Use Cases

Process scheduling in operating systems, asynchronous message brokering, breadth-first graph traversal, producer-consumer buffering, and network packet sequencing.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.