Phương hướng giải quyết cho vấn đề này là cho phép cấp phát bộ nhớ cho một cấu trúc mới khi cần thiết... C cho phép ta thực hiện điều này thông qua cáhc cấp phát bộ nhớ động bằng:malloc
Trang 1CHƯƠNG VIII DANH SÁCH MÓC NỐI
Ta thương sử dụng mảng cấu trúc để xử lý với nhóm dữ liệu Đây là một cách tiếp cận đúng khi ta biết trước chính xác số các cấu trúc cần có Tuy nhiên, khi con số này không rõ ràng, mãng sẽ trở nên khá tốn kém vì chúng phải được cấp phát đủ bộ nhớ để hoạt động Bố nhớ này được đăng ký và sẽ không dành cho nhứng tác vụ khác ngay cả khi ta chỉ dùng một sô nhỏ các phần tử mảng
Phương hướng giải quyết cho vấn đề này là cho phép cấp phát bộ nhớ cho một cấu trúc mới khi cần thiết
Trang 2C cho phép ta thực hiện điều này thông qua cáhc cấp phát bộ nhớ động bằng:
malloc() và calloc()Nhưng các cấu trúc nếu được cấp pháp xong sẽ không có đảm báo nào rằng các cấu trúc sẽ được đặt liên tiếp nhau trong bộ nhớ Do đó điều cần thiết là kỹ thuật để nối kết tất cả các cấu trúc lại với nhau
Phương cách thông dụng để kết nối các phần tử đó lại là dùng danh sách liên kết (Linked list)
Trang 3
I Danh sách liên kết đơn:
Ví dụ: Định nghĩa một danh sách liên kết để chứa các số nguyên
Trang 42 Các phép toán trên danh sách liên kết
a Cấp phát bô nhớ cho biến con trỏ mới
Cú pháp:
Point_New = (struct Point_Name *) malloc
(sizeof(struct Point_Name)
Trang 5Vê duû:
typedef struct Point POINT;
POINT Head, Last, p;
CreatNode(){
p=(POINT *) malloc (POINT)
if (Head==(POINT* ) NULL)
Head=Last=p;
else{
Last=Head;
Trang 6while (Last->Next!= (POINT*) NULL)Last=Last->Next;
Trang 7b Xoá một con trỏ:
Cú pháp:
free(Point_Variable)Giải phóng vùng nhớ được trỏ bởi Point_Variable
c Các phép toán thương dùng trong danh sách liên
kết
Tạo một phần tư của danh sách
Điều phải làm là cấp pháp bộ nhớ cho cấu trúc và trả về con trỏ trỏ đến vùng nhớ này
Ví dụ:
Trang 8printf(“Malloc falled.\n”);
exit(1);
} printf(“Input data for Node info = ”); scanf(“%d”, p->info);
p->Next = NULL return p;
}
Trang 9Bổ sung phần tư vào danh sách
Hàm CreatNode() chỉ cấp phát bộ nhớ nhưng nó
không nối phần tử này vào danh sách Để làm điều này,
ta cần thêm một hàm nữa, gọi là hàm AddNode() Được định nghĩa như sau:
static POINT *Head;
void AddNode(POINT *e)
Trang 10for (p=Head; p->Next!=NULL; p=p->Next);
Chèn phần tư vào danh sách
Để chèn phần tử vào danh sách liên kết, ta phải chỉ rỏ phần tử mới sẽ được chèn vào vị trí nào.Sau đây là hàm sẽ thực hiện công việc trên
Trang 11void InsertNode(POINT *p, POINT *q)
{
if (p=NULL || q=NULL || p==q || q->Next ==p)
{ printf (“Cannot Insert \n”);
Trang 12 Xoá phần tư vào danh sách
Xoá một phần tử khỏi danh sách liên kết đơn, ta cần phải tìm phần tử trước phần tử cần xoá để nhằm mục đích nối lại với phần tử sau phần tử cần xoá Ta dùng hàm free() để giải phống bộ nhớ chiếm bởi
phần tử bị xoá
Có thể xây dưng là:
void DeleteNode(POINT *goner){
POINT *p;
p=Head;
if (goner ==Head)
Head = goner->Next;
Trang 13free(goner)
};
Trang 14Tìm phần tư vào danh sách
Thật khó tạo một hàm FindNode() tổng quát, bởi vì khi tìm kiếm thì ta phải dựa vào một trong những trường dữ liệu của cấu trúc, điều này phụ thuộc vào cấu trúc dang sử dụng Để viết hàm FindNode() tổng quát ta phảisử dụng con trỏ trỏ đến hàm
Với cấu trúc trên ta xây dựng hàm FindNode() như sau:
Trang 16II Danh sách đa liên kết
Trang 17Ví dụ: Định nghĩa một danh sách liên kết để chứa các số nguyên.
Trang 18III STACK và QUEUE
1 STACK
Là danh sách có móc nối đặc biệt Mặc dầu ta có thể thực hiệm nhiều phép toán trên danh sách
tổng quát, Stack vẫn có những tính chất riêng
biệt: chỉ cho phép thêm và xoá bỏ các phần tử ở một vị trí duy nhất, tại đỉnh của Stack
Với đặc trưng như vậy thì Stack có kiểu cấu trúc dữ liệu là LIFO (Last In First Out)
Trang 19a Khởi tạo Stack
Sử dụng mảng:
int stack[100], p;
Stackinit(){
p=0;
}Sử dụng danh sách liên kết
struct Node { int info;
struct Node *Next; };
Trang 20typedef struct Node NODE;
Trang 21b Đẩy dữ liệu vào Stack
Trang 22Push(int a) {
q=(NODE *) malloc (sizeof *q);
Trang 23Sử dụng danh sách liên kết:
Pop(){
q=Head->Next;
Head->Next=q->Next; x=q->info;
}
Trang 24d Kiểm tra Stack rỗng
Sử dụng mảng:
int stackempty(){
return !p;
}Sử dụng danh sách liên kết:
int StackEmpty(){
return Head->Next==p;}
Trang 25Ví dụ: Xây dựng stack bằng danh sách liên kêt:
Trang 30printf("\nAn Enter de tiep tuc/ESC de thoi nhap"); c=getchar();
c=getch();
}
while(c!=ESC);
printf("\nCac gia tri trong Stack\n");
while (!StackEmpty()) printf("%d ",Pop());
printf("\nAn ESC de ket thuc");
getch();
}
Trang 312 Queue
Queue hay còn gọi là hàng đợi, đây là một kiểu danh sách đặc biệt Các phần tử được thêm vào từ một đầu, được gọi là đầu sau, và lấy ra một đầu khác, được gọilà đầu trước
Cấu trúc này được sử dụng trong các tình huống lập trình cần xử lý một dãy các phần tử theo một trật tự cố định Việc xử lý này gọi là FIFO (First Int First Out)