Nội Dung• Kiểu cấu trúc dữ liệu struct – Khai báo và sử dụng – Truyền tham số cho hàm • Các cách định nghĩa kiểu DL có cấu trúc • Danh sách liên kết... Dữ Liệu Kiểu Cấu Trúc• Cấu trúc: –
Trang 1Tin Học Cơ Sở 4
Kiểu dữ liệu có cấu trúc
Danh sách liên kết
Trang 2Nội Dung
• Kiểu cấu trúc dữ liệu struct
– Khai báo và sử dụng
– Truyền tham số cho hàm
• Các cách định nghĩa kiểu DL có cấu trúc
• Danh sách liên kết
Trang 3• Điểm khác biệt cơ bản:
– Phải định nghĩa kiểu cấu trúc struct trước khi khai báo biến kiểu này
Trang 4Cấu Trúc – Ví Dụ
• Kiểu cấu trúc dữ liệu:
– Thành phần khác kiểu
– Các thành phần xác định trước
• Ví dụ: Tên Trường Dữ Liệu Kiểu Dữ Liệu
HoTen Trach Van
Doanh
char[]
MSSV 1234567 int MonHoc INT1006 char*
NgaySinh 01/01/1995 char*
Trang 5Dữ Liệu Kiểu Cấu Trúc
• Cấu trúc:
– Tập hợp các biến, có thể khác kiểu, được nhóm vào thành một tên đơn
– Hỗ trợ tổ chức dữ liệu phức tạp vào cùng một thực thể
– Hỗ trợ làm việc giữa các dữ liệu của cùng một thực thể
– Đôi khi được biết đến như bản ghi.
Trang 6Dữ Liệu Kiểu Cấu Trúc
• Định nghĩa struct toàn cục
– Ngoài/Trước int main()
– Mục đích: tất cả các hàm đều hiểu
• Không được cấp phát bộ nhớ
– Chỉ có mục đích miêu tả cấu trúc
– Khác với mảng: được cấp phát ngay
– Cấp phát bộ nhớ cho biến kiểu cấu trúc
(giống biến thông thường)
• Cần bao nhiêu byte cho 1 biến kiểu cấu trúc?
Trang 7Dữ Liệu Kiểu Cấu Trúc
• Để định nghĩa struct , cần cung cấp:
Trang 8Định Nghĩa struct
• Định nghĩa kiểu dữ liệu mới sử dụng struct
struct sinhvien tên kiểu dữ liệu mới
Trang 9Khai Báo Biến Cấu Trúc
• Sau khi định nghĩa kiểu cấu trúc, có thể khai báo biến kiểu này:
struct sinhvien sinhVien1;
– Giống khai báo các biến kiểu đơn khác
– Bao gồm các giá trị thành phần
• Giống các thành phần định nghĩa trong struct sinhvien
Trang 10• Gọi tên là “biến thành phần"
– Các phần của biến kiểu cấu trúc
– Kiểu cấu trúc struct khác nhau có thể có cùng tên biến thành phần
• Biến thành phần là cục bộ hay toàn cục?
Trang 11Khởi Tạo Biến Cấu Trúc
• Có thể khởi tạo khi khai báo
struct ngay {
int ngay;
int thang;
int nam;
};
struct ngay homNay = {1, 4, 2014};
–Cung cấp dữ liệu ban đầu cho biến thành phần ngay khi khai báo
Trang 12Khởi Tạo Biến Cấu Trúc
• Hoặc khai báo rồi khi cần mới khởi tạo
struct ngay {
Trang 13Cấu Trúc – Phép Gán
• Khai báo 2 biến cấu trúc:
struct ngay homQua, homNay;
– Cả 2 biến đều là kiểu cấu trúc “struct ngay”
Trang 14Cấu Trúc – Các Phép Toán Khác
• Các phép toán khác KHÔNG được đĩnh nghĩa
– So sánh bằng/khác (==, !=) (homQua == homNay biểu thức không hợp lệ) – So sánh thứ tự (<, >, )
(homQua < homNay biểu thức không hợp lệ) – Các phép toán
(homQua + homNay biểu thức không hợp lệ) – In & cập nhật
(printf & scanf không hợp lệ)
• Phải viết các phép toán này
Trang 15Cấu Trúc & Con Trỏ
• Giống các kiểu dữ liệu khác:
– struct x * là con trỏ tới struct x
– Toán tử & trả về địa chỉ của biến cấu trúc
• Theo thứ tự ưu tiên: “.” được ưu tiên trước “*”
• Nếu p là con trỏ trỏ tới cấu trúc struct x và a là một trường của cấu trúc đó:
– *p.a tương đương *(p.a) không hợp lệ
Trang 16Cấu Trúc & Con Trỏ
Trang 17Định Nghĩa Kiểu Khác
khác:
typedef float Floating;
• Sau này, nếu cần đổi độ chính xác, chỉ cần đổi:
typedef double Floating;
Mà không cần phải thay đổi mã
Trang 18Kết hợp struct & typedef
struct sinhvien { char ten[30];
Trang 20Kiểu Tự Tham Chiếu
với các trường là tham chiếu tới một đối tượng có
Trang 21Danh Sách Liên Kết
• Xem xét kiểu dữ liệu như sau:
– Danh sách có thể tăng lên
– Phần tử có thể được lần lượt thêm vào danh sách – Mỗi phần tử là một số
Trang 22Danh Sách Liên Kết
• Làm sao có thể tạo danh sách như vậy trong C
• Có thể sử dụng mảng Tuy nhiên phải kiểm tra điều kiện mảng Nếu đầy phải tạo mảng mới !!!
• Cách khác: sử dụng kiểu tự tham chiếu
• Mỗi phần tử trong danh sách liên kết cần có:
– Dữ liệu
– Kết nối đến phần tử tiếp theo
• Những phần tử trong cấu trúc dữ liệu kiểu như vây thường được gọi là Nút/Nốt
Trang 23Nút & Danh Sách Liên Kết
Trang 25Nút & Con Trỏ
head
Trang 26Con Trỏ ĐẦU
• Hình hộp head không phải là một nút:
QuanBaiPtr head;
– Là một con trỏ tới một nút
– Chỉ tới nút đầu tiên trong danh sách
• head sử dụng để lưu vị trí đầu của danh sách
• Đồng thời cũng là tham chiếu khi truyền cho hàm
Trang 28Dấu Kết Thúc
• Sử dụng NULL để dánh dấu kết thúc
– Ra hiệu không còn kết nối nào sau nút này
• Dấu kết thúc cho danh sách liên kết
cũng giống như cho mảng không đầy
Trang 29Dấu Kết Thúc
head
Trang 30Tạo Nút Đầu Tiên
• ListNodePtr head;
– Khai báo biến con trỏ head
head = (ListNodePtr) malloc
(sizeof(struct ListNode));
strcpy(head->ten, “nut dau tien”); head->key = 1;
head->next = NULL;
– Nút đầu tiên của danh sách (head)
– Cập nhật dữ liệu cho nút đầu tiên
– Kết nối tới NULL do chỉ có 1 nút
Trang 31Thêm Một Nút Vào Sau head
• Tạo một nút mới newNode
Trang 32Thêm Một Nút Vào Cuối
Danh Sách Liên Kết
• Như trước, tạo một nút mới newNode
• Tìm vị trí cuối cùng của danh sách, thêm
ListNodePtr currentNode = head;
while (currentNode->next != NULL)
currentNode = currentNode-> next; currentNode->next = newNode;
Trang 33Tìm Kiếm Trên Danh Sách Liên Kết
//Nếu danh sách trống, head là NULL
//Trả về con trỏ chỉ tới nút đầu tiên có giá
trị //target Nếu không trả về NULL
• Duyệt danh sách đơn giản
– Giống như duyệt mảng
Trang 34Mã Giả Cho Hàm Tìm Kiếm
• while (chưa chỉ tới nút cuối || nút cần tìm)
Trang 35Xóa Một Nút Từ Danh Sách Liên Kết
• Tìm nút cần xóa delNode trong danh sách
• Nếu delNode là nút đầu, chỉ con trỏ
• Nếu không tạo kết nếu giữa nút trước với nút sau của delNode (cần biến phụ để lưu nút trước)
Trang 36Chèn Một Nút Vào Danh Sách Liên Kết
Trang 37Giới Thiệu Cấu Trúc Cây
• Cây là một cấu trúc dữ liệu phức tạp
• Giới thiệu kiến thức cơ bản:
– Khởi tạo, Thao tác
– Sử dụng nút & con trỏ
• Cấu trúc cây có từ 2 con trỏ cho mỗi
nút
Trang 38Cây Nhị Phân
Trang 39Đặc Điểm Của Cấu Trúc Cây
Trang 40Cây & Đệ Quy
• Cây có cấu trúc đệ quy