Thiết kế cấu trúc nút
typedef struct Node {
void* payload;
struct Node* next;
} Node;
payload: Con trỏ kiểuvoid*lưu dữ liệu, cho phép linh hoạt với nhiều kiểu dữ liệu.next: Con trỏ đến nút tiếp theo trong danh sách.
Thiết kế cấu trúc danh sách
typedef struct LinkedList {
Node head;
int length;
} LinkedList;
head: Nút đầu tiên (không chứa dữ liệu thực), dùng làm điểm khởi đầu.length: Số lượng phần tử thực tế trong danh sách.
Khởi tạo danh sách
LinkedList* createList() {
LinkedList* list = malloc(sizeof(LinkedList));
if (!list) return NULL;
list->head.payload = NULL;
list->head.next = NULL;
list->length = 0;
return list;
}
Cấp phát bộ nhớ cho danh sách và khởi tạo nút gốc cùng độ dài ban đầu bằng 0.
Chèn phần tử vào vị trí chỉ định
void insertAt(LinkedList* list, int index, void* data) {
if (!list || !data) return;
if (index < 0 || index > list->length)
index = list->length;
Node* current = &list->head;
for (int i = 0; i < index; ++i)
current = current->next;
Node* newNode = malloc(sizeof(Node));
newNode->payload = data;
newNode->next = current->next;
current->next = newNode;
list->length++;
}
Hàm tự động chèn vào cuối nếu vị trí không hợp lệ. Duyệt đến nút trước vị trí cần chèn, sau đó nối nút mới vào.
Duyệt danh sách
void traverse(LinkedList* list, void (*callback)(void*)) {
if (!list) return;
Node* current = list->head.next;
for (int i = 0; i < list->length; ++i) {
callback(current->payload);
current = current->next;
}
}
Gọi hàm callback trên từng phần tử dữ liệu, bắt đầu từ nút đầu tiên sau nút gốc.
Xóa phần tử theo vị trí
void removeAt(LinkedList* list, int index) {
if (!list || index < 0 || index >= list->length)
return;
Node* prev = &list->head;
for (int i = 0; i < index; ++i)
prev = prev->next;
Node* target = prev->next;
prev->next = target->next;
free(target);
list->length--;
}
Tìm nút đứng trước vị trí cần xóa, cập nhật liên kết và giải phóng bộ nhớ của nút bị xóa.
Xóa phần tử theo giá trị
void removeByValue(LinkedList* list, void* value,
int (*equals)(void*, void*)) {
if (!list || !value) return;
Node* prev = &list->head;
Node* current = prev->next;
for (int i = 0; i < list->length; ++i) {
if (equals(current->payload, value)) {
prev->next = current->next;
free(current);
list->length--;
return;
}
prev = current;
current = current->next;
}
}
Sử dụng hàm so sánh do người dùng cung cấp để tìm và xóa nút đầu tiên khớp giá trị.
Xóa toàn bộ danh sách
void clear(LinkedList* list) {
if (!list) return;
Node* current = list->head.next;
while (current) {
Node* next = current->next;
free(current);
current = next;
}
list->head.next = NULL;
list->length = 0;
}
Giải phóng tuần tự từng nút dữ liệu, đặt lại con trỏ đầu và độ dài về trạng thái rỗng.
Lấy độ dài danh sách
int size(LinkedList* list) {
return list ? list->length : -1;
}
Trả về số phần tử nếu danh sách hợp lệ, ngược lại trả về -1.
Hủy danh sách
void destroy(LinkedList* list) {
if (!list) return;
clear(list);
free(list);
}
Xóa tất cả phần tử và giải phóng bộ nhớ của cấu trúc danh sách.