Cấu trúc tự trỏ và danh sách liên kết

Một phần của tài liệu Giao trinh C (Trang 94 - 102)

Khi ta lập một chương trình quản lý mà bản thân số biến (cấu trúc) chưa được biết trước, nếu ta sử dụng mảng ( cấp phát bộ nhớ tĩnh ) thì ta ph ải sử dụng số các phần tử là tối đa. Như vậy sẽ có rất nhiều vùng nhớ được cấp phát mà không bao giờ dùng đến. Lúc đó ta có cách để cấp phát bộ nhớ động. Số vùng nhớ cấp ra đủ số biến cần dùng.

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ô :

Các cách để định nghĩa cấu trúc tự trỏ person:

Cách 1 :

typedef struct pp {

char ht[20];

char qq[25];

int tuoi;

struct pp *tiep;

} person;

Cách 2 :

typedef struct pp person struct pp

{

char ht[20];

char qq[25];

int tuoi;

person *tiep;

};

Cách 3 : struct pp {

char ht[20];

char qq[25];

int tuoi;

struct pp *tiep;

};

typedef pp person;

Cấu trúc tự trỏ được dùng để xây dựng danh sách liên kết ( móc nối ), đó là một nhóm các cấu trúc có tính chất sau : ( Móc nối theo chiều thuận ).

 Biết địa chỉ cấu trúc đầu đang được lưu trữ trong một con trỏ nào đó.

 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 sau của danh sách.

 Cấu trúc cuối chứa hằng NULL.

VÝ dô :

Với danh sách này, ta có thể lần lượt từ cấu trúc đầu đến cấu trúc cuối theo chiều từ trên xuống dưới.

Nhóm cấu trúc móc nối theo chiều ngượ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 ) đều chứ đị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 này, ta có thể lần lượt từ cấu trúc cuối lên cấu trúc đầu theo chiều từ dưới lên trên.

Ngoài ra, ta có thể xây dựng các danh sách mà mỗi phần tử chứa hai địa chỉ của cấu trúc trước và cấu trúc sau. Với loại danh sách này, ta có thể truy nhập theo cả hai chiều trên.

Khi làm việc với danh sách móc nối, ta thường phải tiến hành các công việc sau sau :

( Giả sử ta có con trỏ p, trỏpdau chỉ cấu trúc đầu của danh sách, con trỏ tiep là thành phần con trỏ của cấu trúc )

Tạo danh sách mới :

 Cấp phát bộ nhớ cho một cấu trúc

 Nhập một biến cấu trúc vào vùng nhớ vừa cấp

 Gán địa chỉ của cấu trúc sau cho thành phần con trỏ của cấu trúc trước

Duyệt qua tất cả các phần tử của danh sách :

 Đưa trỏ p về trỏ cùng cấu trúc với pdau bằng lệnh : p=pdau

 Để chuyển tiếp đến người tiếp theo ta dùng lệnh : p=p->tiep

 Dấu hiệu để biết đang xét cấu trúc cuối cùng của danh sách là : ...

Pdau NULL

p->tiep==NULL Loại một cấu trúc ra khỏi danh sách :

 Lưu trữ địa chỉ của cấu trú c cần loại vào một con trỏ (Để giải phóng bộ nhớ của cấu trúc này)

 Sửa để cấu trúc trước đó có địa chỉ của cấu trúc cần loại

 Giải phóng bộ nhớ cấu trúc cần loại

Bổ xung hoặc chèn một cấu trúc vào danh sách:

 Cấp phát bộ nhớ và nhập bổ xung

 Sửa thành phần con trỏ trong các cấu trúc có liên quan để đảm bảo mỗi cấu trúc chứa

địa chỉ của cấu trúc tiếp theo

Hàm cấp phát bộ nhớ :

void *malloc(kichthuoc_t kichthuoc);

Hàm lấy trong thư viện alloc.h hoặc stdlib.h.

kichthuoc tính bằng số by te. Hàm sẽ đưa con trỏ về vị trí ô nhớ vừa được cấp hoặc về NULL nếu không đủ bộ nhớ cần thiết. Nếu kichthuoc == 0thì nó trả về NULL.

VÝ dô :

#include "stdio.h"

#include "string.h"

#include "alloc.h"

#include "process.h"

int main() {

char *str;

/* Cấp phát bộ nhớ cho xâu ký tự */

if ((str = malloc(10)) == NULL) {

printf("Not enough memory to allocate buffer \n");

exit(1); /* Kết thúc chương trình nếu thiếu bộ nhớ */

}

/* copy "Hello" vào xâu */

strcpy(str, "Hello");

/* Hiển thị xâu */

printf("String is %s\n", str);

/* Giải phóng bộ nhớ */

free(str);

return 0;

}

VÝ dô :

Tạo một danh sách liên kết. Các biến cấu trúc gồm các trường : Họ tên, Quê quán, tuổi, và một trường con trỏ là Tiếp.

Móc nối theo chiều thuận (Vào trước ra trước FIFO first in first out ):

#include "stdio.h"

#include "alloc.h"

#include "conio.h"

#include "string.h"

typedef struct pp {

char ht[25];

char qq[20];

int tuoi;

struct pp *tiep;

} nhansu;

main() {

char tt;

nhansu *pdau,*pcuoi,*p;

char tam[10];

clrscr();

pdau=NULL;

do {

p=(nhansu*)malloc(sizeof(nhansu));

printf("\n Ho ten : ");

gets(p->ht);

printf(" Que quan : ");

gets(p->qq);

printf(" Tuoi: ");

gets(tam);

p->tuoi=atoi(tam);

if (pdau==NULL) {

pdau=p;

pcuoi=p;

p->tiep=NULL;

} else

{

pcuoi->tiep=p;

pcuoi=p;

p->tiep=NULL;

}

printf("\nBam phim bat ky de tiep tuc, ESC de dung");

tt=getch();

} while(tt!=27) ;

/* Đưa danh sách liên kết ra màn hình, trỏ pdau tro */

printf("\n Danh sach nhu sau :\n");

p=pdau;

while (p!=NULL) {

printf("\n Ho ten: %25s Que : %20s Tuoi :

%d",(*p).ht,(*p).qq,(*p).tuoi);

p=p->tiep;

} getch();

}

Móc nối theo chiều ngược ( Vào sau ra trước LIFO last in first out ):

#include "stdio.h"

#include "alloc.h"

#include "conio.h"

#include "string.h"

typedef struct pp {

char ht[25];

char qq[20];

int tuoi;

struct pp *tiep;

} nhansu;

main() {

char tt;

nhansu *pdau,*pcuoi,*p;

char tam[10];

clrscr();

pdau=NULL;

do {

p=(nhansu*)malloc(sizeof(nhansu));

printf("\n Ho ten : ");

gets(p->ht);

printf(" Que quan : ");

gets(p->qq);

printf(" Tuoi: ");

gets(tam);

p->tuoi=atoi(tam);

if (pdau==NULL) {

pdau=p;

pcuoi=p;

p->tiep=NULL;

} else

{

p->tiep=pcuoi;

pcuoi=p;

}

printf("\nBam phim bat ky de tiep tuc, ESC de dung");

tt=getch();

} while(tt!=27) ;

/* Đưa danh sách liên kết ra màn hình, trỏ pdau tro */

printf("\n Danh sach nhu sau :\n");

p=pcuoi;

while (p!=NULL) {

printf("\n Ho ten: %25s Que : %20s Tuoi :

%d",(*p).ht,(*p).qq,(*p).tuoi);

p=p->tiep;

} getch();

}

Chương 9 tËp tin - file

Một phần của tài liệu Giao trinh C (Trang 94 - 102)

Tải bản đầy đủ (PDF)

(141 trang)