V. Kiểu dữ liệu có cấu trúc 5.1 Tệp định kiểu
Chương III Con trỏ và cấu trúc động 6.1 Quản lý vùng nhớ Heap
6.1. Quản lý vùng nhớ Heap Vùng Heap chưa dùng Vùng Heap đã cấp phát Vùng đệm Vùng Stack đã dùng Vùng Stack chưa dùng Data Segment Code Segment DOS
Chương III Con trỏ và cấu trúc động
Một số hàm quản lý bộ nhớ
MemAvail: Tổng dung lượng được phép sử dụng trên Heap
MaxAvail: Dung lượng khối lớn nhất còn tự do trên Heap
Kích thước đối tượng được xác định bởi Sizeof(đt)
Khi MaxAvail < Sizeof(đt) thì không thể xin cấp phát vùng nhớ cho đối tượng trên Heap
Địa chỉ bắt đầu và kết thúc của Heap: HeapOrg và HeapEnd, Write(Seg(HeapOrg^),’:’,ofs(HeapOrg^)); Biến HeapPtr: Địa chỉ đỉnh Heap, địa chỉ đáy của
Chương III Con trỏ và cấu trúc động
6.2. Thủ tục cấp phát bộ nhớ cho con trỏ định kiểu
Ct là con trỏ định kiểu, thực hiện cấp phát qua lời gọi New(ct);
Thực hiện
Cấp phát vùng nhớ trên Heap với kích thước kiểu dữ liệu mà con trỏ trỏ tới
Tạo 1 biến động định kiểu ct^ có thể truy nhập vào vùng dữ liệu của đối tượng
Lưu địa chỉ đối tượng vào con trỏ ct
Thu hồi vùng nhớ, gọi Dispose(ct);
Biến ct vẫn tồn tại, nhưng dữ liệu trong vùng dành cho ct sẽ không được bảo vệ, dành cho việc khác
Chương III Con trỏ và cấu trúc động
6.3. Thủ tục cấp phát bộ nhớ cho con trỏ không định kiểu
Getmem (ct,n): Cấp n byte cho ct
Freemem (ct,n): Thu hồi n byte bộ nhớ cấp phát cho ct
n:= Imagesize(x1,y1,x2,y2);
Chương III Con trỏ và cấu trúc động
6.4. Thu hồi nhiều vùng nhớ
Để thu hồi 1 lúc nhiều hoặc toàn bộ vùng Heap
Khai báo 1 con trỏ ct không kiểu lưu trữ địa chỉ ô nhớ bắt đầu thu hồi
Đánh dấu vị trí bắt đầu thu hồi bởi Mark(ct)
Thu hồi vùng nhớ Release(ct);
Ví dụ 1
Chương III Con trỏ và cấu trúc động
7. Danh sách liên kết và hàng đợi
Danh sách là 1 tập hữu hạn các phần tử liên kết với nhau, trường hợp tổng quát nhất mỗi phần tử là một bản ghi
Gồm trường dữ liệu và trường liên kết, trường liên kết là kiểu con trỏ
Trường liên kết trỏ vào địa chỉ bản ghi kế tiếp
Nếu bản ghi hiện thời là bản ghi kế tiếp, con trỏ sẽ trỏ vào Nil
Danh sách chưa có phần tử nào được gọi là danh sách rỗng
Chương III Con trỏ và cấu trúc động
7. Danh sách liên kết và hàng đợi
Khai báo danh sách
Type DataType = {Khai báo kiểu dữ liệu}; PtrType = ^ Node;
Node = Record
Data:DataType; Next:PtrType; End;
Chương III Con trỏ và cấu trúc động
7. Danh sách liên kết và hàng đợi
Thêm một phần tử vào danh sách, có 3 khả năng
Phần tử mới được thêm vào đầu danh sách
Phần tử mới được nối vào cuối danh sách
Chương III Con trỏ và cấu trúc động
7.1. Danh sách liên kết ngược (Ngăn xếp - Stack)
Trường liên kết của phần tử tạo ra sau luôn trỏ vào phần tử tạo ra trước đó, trường liên kết của phần tử tạo ra đầu tiên trỏ vào Nil
Liên kết kiểu LIFO (Last In First Out)
Chương III Con trỏ và cấu trúc động
7.2. Danh sách liên kết thuận (Hàng đợi - Queue)
Phần tử nhập trước được lấy ra trước (FIFO)
Sử dụng 2 con trỏ: ctdau (First), ctcuoi (Last)
Ctdau luôn trỏ vào phần tử đầu tiên, ctcuoi luôn trỏ vào phần tử cuối cùng của danh sách
Chương III Con trỏ và cấu trúc động
7.3. Các thao tác trên danh sách
Khởi tạo danh sách rỗng
Ctdau:=nil; {First:=nil}
Duyệt danh sách: Lần lượt đi qua các nút của danh sách, sử dụng con trỏ trung gian ct (CurrPtr) trỏ tới nút đầu tiên rồi đi tiếp theo các trường liên kết, xử lý dữ liệu ở mỗi nút
Chương III Con trỏ và cấu trúc động
7.3. Các thao tác trên danh sách
Duyệt danh sách Ví dụ ct:=ctdau; {CurrPtr:=First} while (ct <> nil) do begin {Xử lý ct^.Dữ liệu} ……….. ct:=ct^.Tiếp; end;
Chương III Con trỏ và cấu trúc động
7.3. Các thao tác trên danh sách
Chèn 1 nút vào danh sách
Chèn 1 phần tử có nội dung Item vào danh sách
Vị trí cần chèn được xác định là sau nút đang được trỏ bởi con trỏ PredPtr (con trỏ này rỗng thì vị trí cần chèn là vị trí đầu tiên)
Chương III Con trỏ và cấu trúc động
7.3. Các thao tác trên danh sách
Các bước:
Xin cấp phát 1 nút mới cho con trỏ TempPtr để lưu Item
Nối nút này vào DS tại vị trí cần chèn
Nếu PredPtr là Nil (chèn vào đầu DS), thực hiện: TempPtr^.Next := First;
First := TempPtr; {Cập nhật lại vị trí con trỏ đầu} Trái lại, chèn vào sau PredPtr
TempPtr^.Next := PredPtr^.Next; PredPtr^.Next := TempPtr;
Chương III Con trỏ và cấu trúc động
7.3. Các thao tác trên danh sách
Thực hiện
New(TempPtr);
TempPtr^.Data := Item; if PredPtr = nil then begin TempPtr^.Next:=First; First:=TempPtr; end else begin TempPtr^.Next := PredPtr^.Next; PredPtr^.Next := TempPtr; end;
Chương III Con trỏ và cấu trúc động
7.3. Các thao tác trên danh sách
Xóa 1 nút khỏi danh sách
Xóa nút đứng sau nút đang được trỏ bởi con trỏ PredPtr (nếu nút này rỗng, nút đầu tiên bị xóa)
Ghi nhận TempPtr là con trỏ cần xóa, gán TempPtr bằng PredPtr^.Next (nếu PredPtr = nil thì TempPtr bằng First)
Loại nút cần xóa ra khỏi DS, đặt lại PredPtr^.Next bằng TempPtr^.Next (nếu PredPtr = nil thì First = TempPtr^.Next)
Chương III Con trỏ và cấu trúc động
7.3. Các thao tác trên danh sách
Mô hình xóa
if First <> Nil then {xóa DS khác rỗng} begin
if PredPtr = nil then begin TempPtr:=First; First:=TempPtr^.Next; end else begin TempPtr := PredPtr^.Next; PredPtr^.Next := TempPtr^.Next; end; Dispose(TempPtr); end;
Chương III Con trỏ và cấu trúc động
7.3. Các thao tác trên danh sách
Xây dựng danh sách
a. Nối nút mới vào đầu danh sách
Đặt trường liên kết của nút mới trỏ vào nút đầu
Ghi nhận lại nút đầu là nút mới
First:=nil; {khởi tạo con trỏ rỗng} New(TempPtr); {cấp phát nút mới}
TempPtr^.Data := Item; {Ghi nhận dữ liệu} TempPtr^.Next:=First; {Nối vào trước First} First:=TempPtr; {Ghi nhận lại First}
Chương III Con trỏ và cấu trúc động
7.3. Các thao tác trên danh sách
b. Nối nút mới vào cuối danh sách
Tổ chức thêm con trỏ Last (ctcuoi) luôn trỏ tới cuối danh sách
Chương III Con trỏ và cấu trúc động
b. Nối nút mới vào cuối danh sách
First:=nil;
While not stop do Begin
New(TempPtr);
TempPtr^.Data := Item; if First = nil then
First := TempPtr; else Last^.Next:=TempPtr; Last:=TempPtr; Last^.Next := nil; end
Chương III Con trỏ và cấu trúc động
7.3. Các thao tác trên danh sách
Tìm kiếm 1 nút trong danh sách
Tìm kiếm nút có nội dung là Item
Sử dụng con trỏ trung gian CurrPtr
CurrPtr := First;
while (CurrPtr <> Nil) and (CurrPtr^.Data <> Item) do CurrPtr:=CurrPtr^.Next;
Chương III Con trỏ và cấu trúc động
7.3. Các thao tác trên danh sách
Tìm kiếm phục vụ cho việc xóa hay chèn, cần xác định nút đi trước vị trí cần xóa hoặc chèn
Giả sử DS được sắp xếp theo chiều tăng dần của trường data
Cần chèn nút có nội dung Item vào đúng vị trí của nó trong danh sách
Sử dụng PredPtr: Nút đi trước nút cần chèn
CurrPtr: Nút đi sau nút cần chèn
Chương III Con trỏ và cấu trúc động
8. Cây nhị phân
8.1. Khái niệm cây (Tree)
Là tập hợp hữu hạn các nút, trong đó có 1 nút gọi là gốc (root), giữa các nút có quan hệ phân cấp (cha-con)
Chương III Con trỏ và cấu trúc động
8.1. Khái niệm cây (Tree)
Định nghĩa cây theo cách đệ quy
Một nút là cây, nút đó cũng là gốc của cây
Nếu n là 1 nút và T1, T2, …, Tk là các cây với n1, n2, …, nk lần lượt là các gốc thì 1 cây T sẽ được tạo lập bằng cách cho nút n trở thành cha của các nút n1, n2, …, nk Trên cây này, n là gốc, T1, T2, …, Tk là cây con
(subtrees) của gốc, khi đó n1, n2, …, nk là con của n Tồn tại 1 cây không có nút nào (Null Tree)
Chương III Con trỏ và cấu trúc động
8.1. Khái niệm cây (Tree)
A
B C
ED D
Chương III Con trỏ và cấu trúc động
8.1. Khái niệm cây (Tree)
++ / + / v u y + t z * x
Chương III Con trỏ và cấu trúc động
8.1. Khái niệm cây (Tree)
Số nút con của 1 nút được gọi là cấp (degree) của nút đó (bậc tự do)
Nút có cấp bằng không được gọi là nút lá (leaf) hay nút tận cùng (terminate node)
Cấp cao nhất của nút trên cây gọi là cấp của cây đó
Gốc của cây có số mức (level) là 1, nếu cha có số mức là i thì con có số mức là i+1
Chiều cao (height) hay chiều sâu (depth) của 1 cây là số mức lớn nhất của nút trên cây
Chương III Con trỏ và cấu trúc động
8.2. Cây nhị phân (Binary Tree) 8.2.1. Định nghĩa và tính chất
Định nghĩa
Cây nhị phân là cây mà mọi nút trên cây chỉ có tối đa 2 con
Phân biệt cây con trái (left subtree) Cây con phải (right subtree)