Cấu trúc dữ liệu ngăn xếp và hàng đợi trong C

Ngăn xếp và hàng đợi là hai cấu trúc tuyến tính đặc biệt, khác với danh sách thông thường cho phép chèn/xóa tại bất kỳ vị trí nào, cả hai chỉ cho phép thao tác tại các đầu cố định.

Ngăn xếp (Stack) tuân theo nguyên tắc FIFO ngược — LIFO (Last In, First Out): phần tử được thêm vào cuối cùng sẽ được lấy ra đầu tiên. Trong một ngăn xếp:

  • Đỉnh ngăn xếp (top): vị trí duy nhất cho phép chèn (push) và loại bỏ (pop).
  • Đáy ngăn xếp (bottom): đầu cố định, không thay đổi trong suốt vòng đời.

Dựa trên cách quản lý bộ nhớ và hướng mở rộng, ngăn xếp có thể phân loại thành: ngăn xếp tăng khi rỗng (empty-increasing), giảm khi rỗng (empty-decreasing), tăng khi đầy (full-increasing), hoặc giảm khi đầy (full-decreasing).

Khai báo cấu trúc ngăn xếp tuần tự

typedef int Element;
typedef struct {
    Element *buffer;
    size_t capacity;
    size_t size;
} ArrayStack;

Hàm khởi tạo ngăn xếp động

ArrayStack* stack_create(size_t max_size) {
    if (max_size == 0) return NULL;

    ArrayStack* s = malloc(sizeof(ArrayStack));
    if (!s) return NULL;

    s->capacity = max_size;
    s->size = 0;
    s->buffer = malloc(max_size * sizeof(Element));
    if (!s->buffer) {
        free(s);
        return NULL;
    }
    return s;
}

Kiểm tra trạng thái

int stack_is_full(const ArrayStack* s) {
    return s->size >= s->capacity;
}

int stack_is_empty(const ArrayStack* s) {
    return s->size == 0;
}

Thao tác chèn và loại bỏ

int stack_push(ArrayStack* s, Element val) {
    if (stack_is_full(s)) return -1;
    s->buffer[s->size++] = val;
    return 0;
}

Element stack_pop(ArrayStack* s) {
    if (stack_is_empty(s)) return -1;
    return s->buffer[--s->size];
}

Ngăn xếp liên kết đơn

Sử dụng danh sách liên kết với thao tác đầu danh sách làm đỉnh ngăn xếp:

#include "list.h"
#include <stdio.h>

typedef struct {
    struct list_head link;
    int value;
} StackNode;

int main() {
    struct list_head head;
    INIT_LIST_HEAD(&head);

    // Đẩy 5 phần tử vào ngăn xếp (đầu danh sách)
    for (int i = 1; i <= 5; ++i) {
        StackNode* node = malloc(sizeof(StackNode));
        node->value = i;
        list_add(&node->link, &head);
    }

    // Pop lần lượt: in giá trị rồi giải phóng
    struct list_head *pos, *tmp;
    list_for_each_safe(pos, tmp, &head) {
        StackNode* n = list_entry(pos, StackNode, link);
        printf("%d ", n->value);
        list_del(pos);
        free(n);
    }
    printf("\n");
    return 0;
}

Hàng đợi liên kết đơn

Hàng đợi tuân theo nguyên tắc FIFO (First In, First Out). Thêm vào cuối (tail), lấy từ đầu (head):

#include "list.h"
#include <stdio.h>

typedef struct {
    struct list_head link;
    int payload;
} QueueNode;

int main() {
    struct list_head queue;
    INIT_LIST_HEAD(&queue);

    // Enqueue 5 phần tử bằng cách chèn vào đuôi
    for (int i = 1; i <= 5; ++i) {
        QueueNode* qn = malloc(sizeof(QueueNode));
        qn->payload = i;
        list_add_tail(&qn->link, &queue);
    }

    // Dequeue: lấy từ đầu danh sách
    struct list_head *it, *next;
    list_for_each_safe(it, next, &queue) {
        QueueNode* q = list_entry(it, QueueNode, link);
        printf("%d ", q->payload);
        list_del(it);
        free(q);
    }
    printf("\n");
    return 0;
}

Thẻ: C Stack queue linked-list Data-Structures

Đăng vào ngày 22 tháng 5 lúc 16:38