6.2.1. Cấp phát bộ nhớ động
Trong thực tế chúng ta gặp nhiều bài toán ch−a biết phải xử lý chính xác bao nhiêu đối t−ợng. Th−ờng thì phải khai báo số l−ợng phần tử tối đa, nh− vậy trong nhiều tr−ờng hợp sẽ lãng phí nhiều ô nhớ không cần thiết, ch−ơng trình không tối −u ...
Để tối −u hoá hệ thống, tăng tốc độ xử lý ... chúng ta sẽ sử dụng ph−ơng pháp cấp phát bộ nhớ động, các đối t−ợng xử lý đ−ợc tự động cấp phát số ô nhớ đúng theo yêu cầu thực tế.
Các hàm cấp phát bộ nhớ của C nằm trong tệp alloc.h, do đó để sử dụng đ−ợc các hàm này phải có khai bao sau ở đầu ch−ơng trình:
# include <alloc.h>
Sau đây là một số hàm cấp phát bộ nhớ.
• Hàm void *calloc(unsigned n, unsigned size) : Cấp phát vùng nhớ
n*size byte, nếu thành công hàm trả về địa chỉ đầu vùng nhớ đ−ợc cấp, nếu không đủ bộ nhớ để cấp phát hàm trả về NULL.
• Hàm void *malloc(unsigned n) : Cấp phát vùng nhớ n byte, nếu
thành công hàm trả về địa chỉ đầu vùng nhớ đ−ợc cấp, nếu không đủ bộ nhớ để cấp phát hàm trả về NULL.
• biến_con_trỏ = new data_type: Cấp phát bộ nhớ để l−u trữ đối t−ợng
có kiểu data_type và kết quả trả lại là địa chỉ của đối t−ợng cho biến con trỏ. Ví dụ: float *p = new float;
• Hàm void *free(void ptr) : Giải phóng vùng nhớ đã đ−ợc cấp phát
bởi calloc hoặc malloc do ptr trỏ tới.
• delete biến_con_trỏ: Huỷ bỏ biến_con_trỏ, giải phóng bộ nhớ. 6.2.2. Cấu trúc tự trỏ và danh sách liên kết
Cấu trúc có ít nhất một thành phần là con trỏ kiểu cấu trúc đang định nghĩa gọi là cấu trúc tự trỏ.
Ví dụ:
struct HOSO {
char hoten[25]; int tuoi;
struct HOSO *tiep; }
Cấu trúc tự trỏ đ−ợc dùng để xây dựng các danh sách liên kết (móc nối), đó là các cấu trúc có tính chất:
• Biết địa chỉ của cấu trúc đầu đang đ−ợc l−u trong một con trỏ nào đó (chẳng hạn Pdau).
• Trong mỗi cấu trúc (trừ cấu trúc cuối) chứa địa chỉ của cấu trúc tiếp theo trong danh sách.
• Cấu trúc cuối cùng trong danh sách chứa hằng NULL.
Danh sách có tính chất nh− trên gọi là danh sách liên kết thuận. Với cấu trúc này ta có thể lần l−ợt truy nhập vào các cấu trúc trong danh sách từ đầu tới cuối. Hình ảnh d−ới đây biểu diễn một liên kết thuận.
Pdau addr(ct1) ct1
hoten Lê Thu Hà
tuoi 19 tiep addr(ct2) ct2 hoten Nguyễn An tuoi 25 tiep addr(ct3) ... ctn hoten Vũ Thị Vân tuoi 22 tiep NULL
Ví dụ ch−ơng trình 6.4: Danh sách liên kết thuận.
# include <iostream.h> # include <conio.h> # include <stdio.h> # include <string.h> typedef struct HOSO {
char hoten[25]; int tuoi;
struct HOSO *tiep; } nhansu; nhansu *pdau, *p, p1; void NHAP(); void INRA(); void THEM(); void CHEN(int n); void TIM(int tuoi); void XOA(int n); void main() { clrscr(); NHAP(); clrscr(); INRA(); TIM(20); getch(); delete p; delete pdau; } void NHAP() { char ht[25]; int t; clrscr(); pdau = NULL; while (1) {
cout << "Ho va ten : "; gets(ht); cout << "Tuoi : "; cin >> t; if (pdau == NULL)
{
pdau = new HOSO; p = pdau;
}
else
{
p->tiep = new HOSO; p = p->tiep; } strcpy(p->hoten, ht); p->tuoi = t; p->tiep = NULL; char tl;
cout << "\nNhap nua khong (C/K) ? "; cin >> tl; if (tl == 'k' || tl == 'K') break; } } void INRA() { p = pdau; while (p != NULL) {
cout << (*p).hoten << " " << (*p).tuoi << endl; p = p->tiep;
} } }
// Tim va in ra nguoi khong qua tuoi cho truoc void TIM(int tuoi)
{ p = pdau;
cout << "\nDanh sach nhung nguoi tuoi <= " << tuoi << endl;
int i = 1;
while (p != NULL) {
if (p->tuoi <= tuoi)
{ cout << i << " " << (*p).hoten << endl; i = i+1;
}
p = p->tiep; } }
}
T−ơng tự, danh sách liên kết ng−ợc có các tính chất sau: • Biết địa chỉ cấu trúc cuối.
• Trong mỗi cấu trúc (trừ cấu trúc đầu) chứa địa chỉ của cấu trúc tr−ớc.
• Cấu trúc đầu chứa hằng NULL.
Với danh sách liên kết ng−ợc, ta có thể truy nhập lần l−ợt từ cấu trúc cuối tới cấu trúc đầu.
Danh sách liên kết thuận nghịch: mỗi cấu trúc trong danh sách chứa hai địa chỉ, một địa chỉ của cấu trúc tr−ớc và một địa chỉ của cấu trúc sau nó. Với danh sách loại này ta có thể truy nhập theo hai chiều thuận nghịch.