Bài giảng Kỹ thuật lập trình - Chương 4, Phần 2: Một số cấu trúc dữ liệu và giải thuật căn bản - Vũ Đức Vượng
Chương 4:
Một số cấu trúc dữ liệu và giải thuật căn bản
1.De quy
2.Cau truc du lieu
Mở đầu
• Các bài toán thực tế thường phức tạp
• Hiểu bài toán đặt ra == để giải quyết bài
toán, cần làm gì, không cần làm gì. Do đó,
phải xác định được:
→ Các dữ liệu liên quan đến bài toán
→ Các thao tác cần thiết để giải quyết bài toán
Ví dụ: Bài toán quản lý nhân viên
của một cơ quan
• Cần thực hiện những
• Cần quản lý những
thao tác quản lý nào ?
thô ng tin nào ?
– Tạo ra hồ sơ cho nhân
– Thông tin về nhân
viên: tên, ngày
viên mới vào làm
– Cập nhật một số thông
tin trong hồ sơ
sinh, số bảo hiểm
xã hội, phòng ban
làm việc, … →
– Tìm kiếm thông tin về
1 nhâ n viên
– …
nhân viên ảo
• Ai được phép thực hiện
– …
thao tá c nào?
1. Các khái niệm cơ bản
Cấu trúc dữ liệu
• Cấu trúc dữ liệu là cách tổ chức và thao
tác có hệ thống trên dữ liệu
• 1 cấu trúc dữ liệu :
– Mô tả
• Các dữ liệu cấu thành
• Mối liên kết về mặt cấu trúc giữa các dữ liệu đó
– Cung cấp các thao tác trên dữ liệu đó
– Đặc trưng cho 1 kiểu dữ liệu
1. Các khái niệm cơ bản
Kiểu dữ liệu
• Kiểu dữ liệu cơ bản
• Kiểu dữ liệu có cấu
trúc (structured data
type)
(primitive data type)
– Đại diện cho các dữ
liệu giống nhau,
– Được xây dựng từ các
kiểu dữ liệu (cơ bản,
có cấu trúc) khác
không thể phân chia
nhỏ hơn được nữa
– Thường được các
ngôn ngữ lập trình
định nghĩa sẵn
– Có thể được các ngôn
ngữ lập trình định
nghĩa sẵn hoặc do lập
trình viên tự định
nghĩa
– Ví dụ:
• C/C++: int, long, char,
boolean, v.v.
• Thao tác trên các số
Dữ liệu, kiểu dữ liệu, cấu trúc dữ
liệu
0100110001101001010001
Machine Level Data Storage
3.1415
'A'
28
Primitive Data Types
Basic Data Structures
array
stack
queue
list
High-Level Data Structures
hash table
tree
II. Cấu trúc dữ liệu
• Mang ( bo qua )
• Danh sá ch
• Câ y
• Bảng băm
1. Danh sá ch (list)
• Danh sá ch :
– Tập hợp các phần tử cùng kiểu
– Số lượng các phần tử của danh sách không cố định
• Phân loại:
– Danh sách tuyến tính:
• Có phần tử đầu tiên, phần tử cuối cùng
• Thứ tự trước / sau của các phần tử được xác định rõ ràng, ví dụ sắp theo thứ tự
tăng dần, giảm dần hay thứ tự trong bảng chữ cái
• Các thao tác trên danh sách phải không làm ảnh hưởng đến trật tự này
– Danh sách không tuyến tính: các phần tử trong danh sách không được sắp
thứ tự
• Có nhiều hình thức lưu trữ danh sách
– Sử dụng vùng các ô nhớ liên tiếp trong bộ nhớ → danh sách kế tiếp
– Sử dụng vùng các ô nhớ không liên tiếp trong bộ nhớ → danh sách móc nối
• Danh sách nối đơn
• Danh sách nối kép
1. Danh sá ch
• Thao tác trên danh sách tuyến tính
– Khởi tạo danh sách (create)
– Kiểm tra danh sá ch rỗng (isEmpty)
– Kiểm tra danh sá ch đầy (isFull)
– Tính kích thước (sizeOf)
– Xóa rỗng danh sách (clear)
– Thêm một phần tử vào danh sách tại một ví trí cụ thể (insert)
– Loại bỏ một phần tử tại một vị trí cụ thể khỏi danh sách (remove)
– Lấy một phần tử tại một vị trí cụ thể (retrieve)
– Thay thế giá trị của một phần tử tại một vị trí cụ thể (replace)
– Duyệt danh sách và thực hiện một thao tác tại các vị trí trong danh
sá ch (traverse)
1.1. Danh sách kế tiếp
• Sử dụng một vector lưu trữ gồm một số
các ô nhớ liên tiếp để lưu trữ một danh
sách tuyến tính
– Các phần tử liền kề nhau được lưu trữ trong
những ô nhớ liền kề nhau
– Mỗi phần tử của danh sách cũng được gán
một chỉ số chỉ thứ tự được lưu trữ trong
vector
– Tham chiếu đến các phần tử sử dụng địa chỉ
được tính giống như lưu trữ mảng.
0
1
2
i
last
n-1
1.1. Danh sách kế tiếp
• Ưu điểm của cách lưu trữ kế tiếp
– Tốc độ truy cập vào các phần tử của danh sách
nhanh
• Nhược điểm của cách lưu trữ kế tiếp
– Cần phải biết trước kích thước tối đa của danh sách
• Tại sao?
– Thực hiện các phép toán bổ sung các phần tử mới và
loại bỏ các phần tử cũ khá tốn kém
• Tại sao?
1.1.a. Thêm một phần tử vào một
danh sách kế tiếp
• 2 trường hợp
– insert(index, element): thêm một phần tử element vào một vị trí cụ thể index
– insert(list, element): thêm một phần tử element vào vị trí bất kỳ trong danh sách
list
• Điều kiện tiên quyết:
– Danh sách phải được khởi tạo rồi
– Danh sách chưa đầy
– Phần tử thêm vào chưa có trong danh sách
• Điều kiện hậu nghiệm:
– Phần tử cần thêm vào có trong danh sách
insert(3, ‘z’)
0 1 2 3 4 5 6 7 8 9
z
a b c d e f g h
count=98
1.1.a. Thêm một phần tử vào một
danh sách kế tiếp
Algorithm Insert
Input: index là vị trí cần thêm vào, element là giá trị cần thêm vào
Output: tình trạng danh sách
if list đầy
return overflow
if index nằm ngoài khoảng [0..count]
return range_error
//Dời tất cả các phần tử từ index về sau 1 vị trí
for i = count-1 down to index
entry[i+1] = entry[i]
entry[index] = element
count++
return success;
// Gán element vào vị trí index
// Tăng số phần tử lên 1
End Insert
1.1.b.Xóa 1 phần tử khỏi danh
sách kế tiếp
remove(3, ‘d’)
0 1 2 3 4 5 6 7 8 9
a b c d e f g h
h
count=7
8
1.1.b.Xóa 1 phần tử khỏi danh sách
kế tiếp
Algorithm Remove
Input: index là vị trí cần xóa bỏ, element là giá trị lấy ra được
Output: danh sách đã xóa bỏ phần tử tại index
if list rỗng
return underflow
if index nằm ngoài khoảng [0..count-1]
return range_error
element = entry[index]
count--
//Lấy element tại vị trí index ra
//Giảm số phần tử đi 1
//Dời tất cả các phần tử từ index về trước 1 vị trí
for i = index to count-1
entry[i] = entry[i+1]
return success;
End Remove
.1.c.Duyệt danh sách kế tiếp
Algorithm Traverse
Input: hàm visit dùng để tác động vào từng phần tử
Output: danh sách được cập nhật bằng hàm visit
//Quét qua tất cả các phần tử trong list
for index = 0 to count-1
Thi hành hàm visit để duyệt phần tử entry[index]
End Traverse
1.2. Danh sách nối đơn
• Một phần tử trong
danh sách = một
nút
INFO
N
E
X
T
L
• Quy cách của một
nút
– INFO: chứa thông tin
(nội dung, giá trị)
ứng với phần tử
– NEXT: chứa địa chỉ
của nút tiếp theo
• Để thao tác được
trên danh sách, cần
nắm được địa chỉ
của nút đầu tiên
trong danh sá ch,
tức là biết được
con trỏ L trỏ tới đầu
danh sá ch
Tổ chức danh sách móc nối
• Nút = dữ liệu + móc nối{
• Định nghĩa:
typedef struct node {
int data;
struct node *next; } Node;
• Tạo nút mới:
Node *p = malloc(sizeof(Node));{
• Giải phóng nút:
free(p);
Khởi tạo và truy cập danh sách
móc nối
• Khai báo một con trỏ
Node *Head;
Head là con trỏ trỏ đến nút đầu của danh sách.Khi danh
sách rỗng thì Head =NULL.
• Tham chiếu đến các thành phần của một nút trỏ bởi p
– INFO(p)
– NEXT(p)
• Một số thao tác với danh sách nối đơn
– 1.Thêm một nút mới tại vị trí cụ thể
– 2.Tìm nút có giá trị cho trước
– 3.Xóa một nút có giá trị cho trước
– 4.Ghép 2 danh sách nối đơn
– 5.Hủy danh sách nối đơn
Truyền danh sách móc nối vào hàm
• { Khi truyền danh sách móc nối vào
hàm, chỉ cần truyền Head.
• { Sử dụng Head để truy cập toàn bộ
danh sá ch
– { Note: nếu hàm thay đổi vị trí nút đầu của
danh sách (thêm hoặc xóa nút đầu) thì Head
sẽ không còn trỏ đến đầu danh sách
– { Do đó nên truyền Head theo tham biến
(hoặc trả lại một con trỏ mới)
Tải về để xem bản đầy đủ
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Kỹ thuật lập trình - Chương 4, Phần 2: Một số cấu trúc dữ liệu và giải thuật căn bản - Vũ Đức Vượng", để tải tài liệu gốc về máy hãy click vào nút Download ở trên
File đính kèm:
bai_giang_ky_thuat_lap_trinh_chuong_4_phan_2_mot_so_cau_truc.ppt

