Bài giảng Ngôn ngữ lập trình C - Chương 5: Dữ liệu kiểu cấu trúc cung cấp cho người học các kiến thức: Khai báo cấu trúc, các thao tác trên biến cấu trúc, mảng cấu trúc, con trỏ cấu trúc và địa chỉ cấu trúc, truyền biến cấu trúc cho hàm, cấu trúc tự trỏ và ứng dụng. Mời các bạn cùng tham khảo.
Chương Dữ liệu kiểu cấu trúc Chương Dữ liệu kiểu cấu trúc Khái niệm Khai báo cấu trúc Các thao tác biến cấu trúc Mảng cấu trúc Con trỏ cấu trúc địa cấu trúc Truyền biến cấu trúc cho hàm Cấu trúc tự trỏ ứng dụng Khái niệm Cấu trúc tập hợp nhiều biến, chúng có kiểu liệu khác nhau, nhóm lại tên để tiện xử lý Cấu trúc gọi ghi số ngơn ngữ lập trình khác, chẳng hạn PASCAL Khái niệm Một số ví dụ cấu trúc: Phiếu ghi lương, gồm có: tên, địa chỉ, lương, phụ cấp, … số thuộc tính lại cấu trúc chứa nhiều thành phần: Tên ( Họ, đệm, tên ), Địa ( Phố, số nhà ), Danh sách sinh viên, gồm có: mã sinh viên, họ tên, ngày sinh, điểm tốn, điểm lý, điểm hóa…; đó, ngày sinh chứa nhiều thành phần ngày, tháng, năm Những dạng sử dụng cấu trúc Định nghĩa kiểu cấu trúc Định nghĩa cấu trúc struct: struct tên_kiểu_cấu_trúc{ Khai báo thành phần cấu trúc }; Ý nghĩa: struct: từ khoá tên_kiểu_cấu_trúc: người lập trình tự đặt thành phần cấu trúc là: biến, mảng, cấu trúc khác định nghĩa trước Ví dụ: struct {int ngaythu; char thang[12]; int nam; }; Định nghĩa kiểu cấu trúc Định nghĩa cấu trúc typedef typedef ; Ví dụ: typedef struct { int ngaythu; char thang[12]; int nam; } ngay; Khai báo biến cấu trúc Giống khai báo biến thông thường Cú pháp: struct ; Ví dụ: struct ngaydi, ngayden; Chú ý: Các biến kiểu cấu trúc khai báo theo mẫu cấp phát nhớ cách đầy đủ cho tất thành phần Khai báo biến cấu trúc Có thể khai báo biến cấu trúc đồng thời với định nghĩa cấu trúc Cú pháp: struct { Thành phần cấu trúc}; Ví dụ: struct { int ngaythu; char thang[12]; int nam; } ngaydi, ngayden; Các thao tác biến cấu trúc Truy cập đến thành phần cấu trúc: Sử dụng dấu để truy cập đến thành phần cấu trúc tên_biến_cấu_trúc.tên_thành_phần tên_biến_cấu_trúc.tên_cấu_trúc_con.tên_thành_phần Ví dụ: a; a.ngaythu=15; printf(“%d”,a.ngaythu); Các thao tác biến cấu trúc Truy cập đến thành phần cấu trúc: Chú ý: Có thể sử dụng phép tốn lấy địa thành phần cấu trúc để nhập số liệu trực tiếp vào thành phần cấu trúc Ví dụ ta viết: scanf("%d",&a.nam); Tuy nhiên ta nên nhập số liệu vào biến trung gian sau gán cho thành phần cấu trúc sau: int year; scanf("%d",&year); a.nam=year; Cấu trúc tự trỏ Một số danh sách liên kết sử dụng cấu trúc tự trỏ: Stack (ngăn xếp): hoạt động theo phương thức Last In – First Out (LIFO) Queue (hàng đợi): hoạt động theo phương thức First In – First Out (FIFO) Binary tree (cây nhị phân): Là cây, node cha có node Node trái có giá trị nhỏ node cha Node phải có giá trị lớn node cha Ứng dụng: DSLK đơn Khái niệm: Danh sách liên kết đơn cấu trúc liệu bao gồm tập node, node gồm: Dữ liệu cần lưu trữ Liên kết đến node (địa node tiếp theo) Link Data Add Node start 60 1000 800 45 800 90 55 90 NULL Ứng dụng: DSLK đơn Ưu điểm: DSLK cấu trúc động, node cấp phát/giải phóng chương trình chạy -> Kích thước danh sách khơng cần phải khai báo trước DSLK thích hợp thực phép toán danh sách (tập hợp) thường bị biến động chèn, xóa phần tử Hạn chế: Mỗi node DSLK phải chứa thêm trường next nên tốn thêm nhớ Tìm kiếm DSLK chậm ta truy xuất ngẫu nhiên, truy xuất từ đầu danh sách Ứng dụng: DSLK đơn Ví dụ 1: DSLK lưu thông tin sinh viên: struct TTSV { char Hoten[20]; int Tuoi; } struct node { struct TTSV data; struct node* next; } struct node *First; Ví dụ 2: DSLK lưu số nguyên struct node { int data; struct node* next; } struct node *First; Ứng dụng: DSLK đơn Khai báo DSLK struct node { int data; struct node *next; }; typedef struct node* List; Khởi tạo DS: void Init(List*); Tạo node có nội dung x: struct node* NewNode(int); Tìm node có nội dung x: struct node* FindNode(List ,int); Thêm node vào đầu DS: int InsertFirst(List*, int); Thêm node vào cuối DS: int InsertAfter(List*, int); Thêm node vào DS: int Insert(List*, int); Xóa node đầu DS: int DeleteFirst(List*); Xóa node cuối DS: int DeleteAfter(List*); Xóa node DS: int Delete(List*); Duyệt DS: void Travel(List); Ứng dụng: DSLK đơn Khởi tạo danh sách: void Init(List *First) { *First = NULL; } First NULL Ứng dụng: DSLK đơn Tạo node có nội dung x: struct node* NewNode(int x) { struct node *p; p = (struct node *)malloc(sizeof(struct node); if (p!=NULL) {p -> data = x; p -> next = NULL;} return (p) } newNode x next NULL Ứng dụng: DSLK đơn Thêm node vào DSLK: Thêm vào đầu danh sách: Tạo node có nội dung x; (newNode = NewNode(x)) Phần next node trỏ tới đầu DSLK Trỏ First tới newNode … L newNode x NULL Ứng dụng: DSLK đơn Thêm node vào DSLK (.t): Thêm vào cuối danh sách Tìm trỏ trỏ tới node cuối (temp) Tạo node newNode(x) Phần next node temp tới newNode … L NULL v temp newNode Ứng dụng: DSLK đơn Thêm node vào DSLK (.t): Thêm vào danh sách: Tìm trỏ (temp) trỏ tới node trước vị trí cần thêm Tạo node newNode(x) Trỏ phần next newNode tới node sau temp Trỏ phần next temp tới newNode … v … L temp x newNode NULL Ứng dụng: DSLK đơn Xóa node DSLK: Xóa node đầu danh sách: Tạo trỏ temp trỏ vào node đầu danh sách Trỏ First tới node thứ danh sách Thu hồi vùng nhớ node (được trỏ temp) L … temp NULL Ứng dụng: DSLK đơn Xóa node DSLK (t.): Xóa node cuối danh sách: Tìm trỏ p trỏ tới node áp cuối, trỏ temp trỏ tới node cuối Phần next p trở tới NULL Thu hồi vùng nhớ node cuối (được trỏ temp) L v v … p temp v v v NULL Ứng dụng: DSLK đơn Xóa node DSLK (t.): Xóa node danh sách: Trỏ temp tới node cần xóa, p tới node trước node cần xóa Phần next p tới node sau node temp Giải phóng vùng nhớ node cần xóa (được trỏ temp) L p … temp v x … NULL Ứng dụng: DSLK đơn Danh sách liên kết vòng v first v … v last • Danh sách liên kết đơi v NULL first v … v last NULL Ứng dụng: DSLK đơn Tìm node có nội dung x … L x … p struct node* FindNode(List L ,int x) { struct node *p; p = L; while (p!=NULL) { if (p->Info == x) return p; p = p->Next; } return (p) } NULL ... Link Data Add Node start 60 1000 800 45 800 90 55 90 NULL Ứng dụng: DSLK đơn Ưu điểm: DSLK cấu trúc động, node cấp phát/giải phóng chương trình chạy -> Kích thước danh sách khơng cần phải... khác nhau, nhóm lại tên để tiện xử lý Cấu trúc gọi ghi số ngôn ngữ lập trình khác, chẳng hạn PASCAL Khái niệm Một số ví dụ cấu tr? ?c: Phiếu ghi lương, gồm có: tên, địa chỉ, lương, phụ cấp,... tr? ?c: (t.) Truy cập thành phần trỏ cấu tr? ?c: Cú pháp: Cách 1: Tên_con_tr? ?-> Tên_thành_phần Cách 2: (*Tên_con_trỏ).Tên_thành_phần Ví dụ: struct *p,*p1,*p2,nc1,nc2,ds[100]; nc1 nam; p 1-> nam;