Cấu trúc dữ liệu và thuật toán hust năm 2024

Cấu trúc dữ liệu là một họ các biến có thể có kiểu dữ liệu khác nhau, được liên kết với nhau theo một cách thức được quy định trước nào đó. Ví dụ như mảng là một dãy các ô có cùng kiểu dữ liệu xác định.

Một số cấu trúc dữ liệu phổ biến như là:

- Mảng

- Danh sách

- Đồ thị

- Ngăn xếp

- Hàng đợi

- Cây

Với các bài viết về cấu trúc dữ liệu này, mình sẽ đề cập tới khái niệm chính và cách cài đặt từng loại cấu trúc dữ liệu.

2. Cấu trúc dữ liệu mảng

Dữ liệu dạng mảng là một dạng dữ liệu vô cùng phổ biến mà chúng ta có thể gặp thường xuyên trong mọi ngôn ngữ lập trình và mọi dự án.

Thông thường mảng thường được lưu trữ trên một dãy liên tiếp các ô nhớ trên bộ nhớ, vì vậy việc truy cập các phần tử trong mảng là cực kỳ nhanh chóng, nhưng lại bất lợi trong việc phân bổ thêm ô nhớ cho mảng.

Mảng thì rất quen thuộc rồi, các ngôn ngữ lập trình đều hỗ trợ hầu như mọi phép toán liên quan tới mảng, nên phần cài đặt mảng mình sẽ không đề cập tới trong phần này.

3. Cấu trúc dữ liệu danh sách liên kết đơn

Danh sách liên kết đơn (hay một số tài liệu đề cập là danh sách móc nối đơn) là danh sách các phần tử mà mỗi phần tử sẽ chứa giá trị và một con trỏ chứa trỏ tới ô kế tiếp của danh sách.

Cấu trúc dữ liệu và thuật toán hust năm 2024

Danh sách liên kết sẽ khắc phục được một số nhược điểm của việc sử dụng mảng đó là:

- Bổ sung một phần tử tốn kém thời gian

- Lãng phí khoảng bộ nhớ trống khai báo ban đầu không dùng đến

- Phải duy trì một khoảng không gian lưu trữ liên tục trong bộ nhớ

3.1 Cài đặt danh sách liên kết đơn

Các ví dụ về cài đặt cấu trúc dữ liệu trong các bài viết mình sẽ sử dụng ngôn ngữ lập trình C.

Khai báo một struct node, và viết 5 hàm tương ứng với 5 phép toán trên danh sách liên kết:

- isEmpty(): kiểm tra danh sách liên kết rỗng

- print_list(): in danh sách phần tử

- push(item): thêm phần tử vào đầu danh sách liên kết

- pop(): loại bỏ phần tử cuối danh sách

- insert_by_index(inx, item): chèn một phần tử vào vị trí bất kỳ trong danh sách liên kết

Tùy thuộc vào từng bài toán, khi cần thêm những chức năng cụ thể nào cho danh sách liên kết thì chúng ta có thể viết thêm các hàm tương ứng để công việc được thực hiện một cách dễ dàng hơn.

include

define INT_MIN -2147483648

struct node {

int data;
struct node *next;
}; struct node* head = NULL; int isEmpty(){
return head == NULL;
} void print_list(){
struct node *current = head;
while(current != NULL){
    printf("%d\n", current->data);
    current = current->next;
}
} // push to front list void push(int item){
struct node* newN = (struct node*) malloc(sizeof(struct node));
newN->data = item;
newN->next = head;
head = newN;
} // pop last void pop(){
struct node* it = head;
if(it->next == NULL){
    head = NULL;
    free(it);
    return;
}
while(it->next->next != NULL){
    it = it->next;
}
struct node* lastN = it->next;
it->next = NULL;
free(lastN);
} void insert_by_index(int item, int inx){
if(inx == 0){
    push(item);
    return;
}
struct node* it = head;
int cnt = 1;
while(cnt < inx){
    it = it->next;
    cnt++;
}
struct node* prev = it;
struct node* next = it->next;
// create new node
struct node* newN = (struct node*) malloc(sizeof(struct node));
newN->data = item;
}

3.2 Kiểm tra danh sách liên kết đơn vừa cài đặt

Chúng ta kiểm tra nhanh về cấu trúc dữ liệu vừa cài đặt có đúng không bằng cách sử dụng các hàm vừa cài đặt để thao tác với cấu trúc dữ liệu và kiểm tra dữ liệu sau khi sử dụng các hàm đã đúng chưa bằng cách in ra (sử dụng hàm print_list()).