Biến tĩnh trong NNLT Vùng nhớ của kiểu dữ liệu tĩnh sẽ được sinh ra khi ta khai báo biến và mất đi khi ra khỏi phạm vi khai báo hoặc khi chương trình kết thúc đối với các biến to
Trang 1CTDL động Danh sách liên kết
Nguyễn Đỗ Thái Nguyên
nguyenndt@hcmue.edu.vn
Trang 26 Các cấu trúc đặc biệt của dslk đơn
7 Chuyển biểu thức trung tố sang biểu thức
hậu tố
8 Định trị biểu thức hậu tố
Trang 31 Đặt vấn đề - ctdl động, tại sao?
typedef struct NGUOI
CTDL động giải quyết được vấn đề này Nó giải quyết như thế nào?
Trang 49/11/2019 CTDL1- N.Đ.T.Nguyên 4
1 Đặt vấn đề - ctdl động, tại sao?
Biến tĩnh trong NNLT
Vùng nhớ của kiểu dữ liệu
tĩnh sẽ được sinh ra khi ta
khai báo biến và mất đi khi ra
khỏi phạm vi khai báo hoặc
khi chương trình kết thúc đối
với các biến toàn cục
Biến tĩnh trong chương trình
không thay đổi được cấu trúc
hay độ lớn trong khi thực thi
Nhu cầu thực tế
Có nhiều biến tĩnh không cần
sử dụng nữa nhưng nó vẫn tồn tại và chiếm bộ nhớ cho đến khi chương trình hủy nó
đi theo đúng cơ chế của biến tỉnh gây lãng phí bộ nhớ
Trong chu kỳ sống của một
số đối tượng dữ liệu có thể thay đổi về cấu trúc, độ lớn như: danh sách học viên có thể tăng lên hoặc giảm xuống
bất hợp lý Vấn đề về hiệu quả sử dụng bộ nhớ
CTDL động giải quyết được vấn đề này Nó giải quyết như thế nào?
Trang 5Hạn chế về kích thước bộ nhớ cho các biến tĩnh
Trang 72 Con trỏ và kiểu dữ liệu động
Trang 89/11/2019 CTDL1- N.Đ.T.Nguyên 8
mất khi ra khỏi phạm vi này
liệu (data segment) hoặc là Stack (đối
với biến nữa tĩnh – các biến cục bộ)
quá trình sống
Biến không động
Trang 92 Con trỏ và kiểu dữ liệu động
Kiểu con trỏ (của 1 kiểu dữ liệu T) cũng vậy gồm:
Tập giá trị là tập địa chỉ của kiểu dữ liệu T tương ứng
Tập thao tác: tạo con trỏ đến đối tượng có kiểu T
Ví dụ: con trỏ số nguyên được khai báo như sau
int *p;
// có kích thước cố định 2 hay 4 byte tùy vào NNLT, loại con trỏ //Con trỏ kiểu int thì có thể lưu được địa chỉ của biến kiểu int
Trang 109/11/2019 CTDL1- N.Đ.T.Nguyên 10
Biến động
Không được khai báo tường minh
Có thể được cấp phát hoặc giải phóng bộ nhớ khi người sử dụng
yêu cầu
Các biến này không theo quy tắc phạm vi (tĩnh)
Vùng nhớ của biến được cấp phát trong Heap
Kích thước có thể thay đổi trong quá trình sống
Con trỏ làm nhiệm vụ quản lý các biến này bằng cách lưu địa chỉ vùng nhớ của chúng
Ví dụ:
int *p,*q;
q=new int[10]; //xin cấp phát 10 vùng kiểu int
… //sử dụng các biến động ở đây
delete [ ]q; //trả lại vùng nhớ cho hệ thống
Biến động
Trang 112 Con trỏ và kiểu dữ liệu động
Trang 129/11/2019 CTDL1- N.Đ.T.Nguyên 12
Trang 132 Con trỏ và kiểu dữ liệu động
Trang 149/11/2019 CTDL1- N.Đ.T.Nguyên 14
Trang 152 Con trỏ và kiểu dữ liệu động
int x;
int *p, *q;
p=&x;
q=&x;
Trang 169/11/2019 CTDL1- N.Đ.T.Nguyên 16
Trang 172 Con trỏ và kiểu dữ liệu động
Trang 189/11/2019 CTDL1- N.Đ.T.Nguyên 18
Trang 192 Con trỏ và kiểu dữ liệu động
Ví dụ về việc xin cấp phát biến động:
printf(“Gia tri cua vung nho do p quan ly: %d”, *p);
delete p; //trả lại vùng nhớ sau khi đã sử dụng xong }
Trang 21cout<<p->tu<< ",“
<<p->mau<<endl;
p=p->lienket;
} }
Trang 229/11/2019 CTDL1- N.Đ.T.Nguyên 22
Mảng là một hình thức liên kết ngầm
Các phần tử trong mảng được cấp phát vùng nhớ một cách liên tiếp nhau
Với T là kiểu dữ liệu cho trước, xét mảng các phần tử kiểu T Ta có:
Address(i)=Address(0)+(i-1)*sizeof(T)
Trang 234 Danh sách liên kết
Danh sách liên kết đơn
Trang 249/11/2019 CTDL1- N.Đ.T.Nguyên 24
Trang 254 Danh sách liên kết
Trang 269/11/2019 CTDL1- N.Đ.T.Nguyên 26
Trang 274 Danh sách liên kết
Trang 289/11/2019 CTDL1- N.Đ.T.Nguyên 28
Trang 294 Danh sách liên kết đơn
Tạo danh sách
Khai báo danh sách liên kết
Khởi tạo danh sách liên kết
Tạo mới một phần tử để thêm vào danh sách liên kết
Thêm vào đầu danh sách
Thêm vào cuối danh sách
Xuất dữ liệu của toàn bộ danh sách liên kết
Thêm vào sau một phần tử cho trước
Tìm kiếm
Tìm một phần tử có khóa cho trước
Tìm một phần tử đứng trước một phần tử cho trước
Hủy danh sách
Hủy một phần tử đầu danh sách
Hủy một phần tử cuối danh sách
Hủy một phần tử sau một phần tử cho trước
Hủy một phần tử có khóa cho trước
Hủy toàn bộ danh sách
Trang 309/11/2019 CTDL1- N.Đ.T.Nguyên 30
typedef struct NODE
{
Trang 314 Danh sách liên kết đơn
void KhoiTao(LIST &l)
{
l.pHead=NULL;
l.pTail=NULL;
}
Việc khởi tạo danh sách liên kết nhằm xác định
danh sách ban đầu mới tạo ra là rỗng
Trang 334 Danh sách liên kết đơn
1 Danh sách rỗng
2 Danh sách đã có phần tử
Trang 349/11/2019 CTDL1- N.Đ.T.Nguyên 34
void AddHead(LIST &l, NODE* add)
{
if(l.pHead==NULL) {
l.pHead=l.pTail=add;
} else {
add->next=l.pHead;
l.pHead=add;
} }
Thêm một phần tử vào đầu danh sách liên kết
Trang 354 Danh sách liên kết đơn
1 Danh sách rỗng
2 Danh sách đã có phần tử
Trang 369/11/2019 CTDL1- N.Đ.T.Nguyên 36
void AddTail(LIST &l, NODE* add)
{
if(l.pHead==NULL) {
l.pHead=l.pTail=add;
} else {
l.pTail->next=add;
l.pTail=add;
} }
Thêm một phần tử vào cuối danh sách liên kết
Trang 374 Danh sách liên kết đơn
printf(“ >%d”,p->data);
p=p->next;
} }
Trang 389/11/2019 CTDL1- N.Đ.T.Nguyên 38
Tìm một phần tử trong danh sách liên kết khi biết khóa (data)
Sử dụng 1 con trỏ phụ p để duyệt tất cả các phần tử trong danh sách liên kết
Trang 394 Danh sách liên kết đơn
NODE* Search(LIST l, int data)
Kết quả trả về là NULL tức là không tìm thấy phần tử có khóa data
Ngược lại nếu tìm thấy thì nó sẽ trả về địa chỉ của phần tử đầu tiên
có khóa data trong danh sách liên kết
Trang 409/11/2019 CTDL1- N.Đ.T.Nguyên 40
Thêm một phần tử vào sau một phần tử cho trước
1 Danh sách rỗng
2 Danh sách đã có phần tử
q
Trang 414 Danh sách liên kết đơn
void AddAfter(LIST &l, NODE* q, NODE* add)
{
if(q!=NULL) {
AddHead(l,add);
} }
Trang 429/11/2019 CTDL1- N.Đ.T.Nguyên 42
NODE* SearchPre(LIST l, NODE* s)
Trang 434 Danh sách liên kết đơn
1 Tách phần tử đầu ra khỏi danh sách
2 Xóa phần tử này
Trang 449/11/2019 CTDL1- N.Đ.T.Nguyên 44
void RemoveHead(LIST &l)
{
if(l.pHead!=NULL) {
Hủy phần tử đầu trong danh sách liên kết
Trang 454 Danh sách liên kết đơn
1 Tách phần tử cuối ra khỏi danh sách
2 Gán pTail = địa chỉ của phần tử kế cuối
3 Xóa phần tử này
Trang 469/11/2019 CTDL1- N.Đ.T.Nguyên 46
void RemoveTail(LIST &l)
Trang 474 Danh sách liên kết đơn
1 Tách phần tử p ra khỏi danh sách liên kết
2 Xóa phần tử này
q
Trang 489/11/2019 CTDL1- N.Đ.T.Nguyên 48
void RemoveAfter(LIST &l, NODE* q)
{
NODE* p;
if(q!=NULL) {
p=q->next;
if(p!=NULL) {
Trang 494 Danh sách liên kết đơn
Trang 509/11/2019 CTDL1- N.Đ.T.Nguyên 50
void Remove (LIST &l, int k)
{
NODE* p=l.pHead,*q=NULL;
while((p!=NULL)&&(p->data!=k)) {
q=p; p=p->next;
} if(p==NULL) return;
if(q!=NULL) {
if(p==l.pTail) {
l.pTail=q;
l.pTail->next=NULL;
} q->next=p->next;
delete p;
} else // p là phần tử đầu tiên (pHead)
RemoveHead(l);
}
Hủy phần tử có khóa k cho trước
Trang 514 Danh sách liên kết đơn
p=l.pHead;
l.pHead=l.pHead->next;
delete p;
} l.pTail=NULL;
}
Trang 529/11/2019 CTDL1- N.Đ.T.Nguyên 52
5 Sắp xếp trên danh sách liên kết
void ListSelectionSort (LIST &l)
{
NODE* min; //trỏ đến pt có data min NODE* i,*j;
for(i = l.pHead;i->next!=NULL;i=i->next) {
Selection Sort – Hoán vị nội dung phần dữ liệu (data)
Trang 535 Sắp xếp trên danh sách liên kết
void ListSelectionSort (LIST &l)
min=i;
minpre=j;
} if(minpre==NULL) {
l.pHead=l.pHead->next;if(min==l.pTail) l.pTail=NULL;
} else {
if(min==l.pTail) l.pTail=minpre;minpre->next=min->next;
} min->next=NULL;
AddTail(lresult,min);
} l=lresult;
2 Tách min ra khỏi danh sách
Trang 54 Các thao tác trên stack:
Push(o): thêm đối tượng vào đâu stack
Pop(): lấy đối tượng ở đầu stack ra khỏi stack và trả về đối tượng đó, nếu stack rỗng thì trả về NULL
isEmpty(): Kiểm tra stack có rỗng hay không
Top(): trả về phần tử nằm ở đầu stack mà không lấy phần tử này
ra khỏi stack
Stack được sử dụng để: khử đệ quy, tổ chức lưu vết của quá trình tìm kiếm theo chiều sâu và quay lui, vét cạn, định trị biểu thức, …
SV tự cài đặt stack bằng mảng và dslk đơn.
Trang 556 Các cấu trúc đặc biệt của dslk đơn
Hàng đợi
Là một vật chứa (container) các đối tượng làm việc theo cơ chế FIFO (first in first out)
Các thao tác trên hàng đợi
EnQueue(o): thêm đối tượng vào hàng đợi
DeQueue(): Lấy đối tượng ra khỏi hàng đợi và trả về đối tượng đó
IsEmpty(): Kiểm tra hàng đợi có rỗng không
Front(): Trả về đối tượng nằm ở đầu hàng đợi mà không hủy nó
SV tự cài đặt hàng đợi bằng mảng và dslk đơn
Trang 569/11/2019 CTDL1- N.Đ.T.Nguyên 56
6 Các cấu trúc đặc biệt của dslk đơn
Trang 577 Chuyển từ trung tố sang hậu tố
Trang 589/11/2019 CTDL1- N.Đ.T.Nguyên 58
7 Chuyển từ trung tố sang hậu tố
Duyệt từ trái sang phải
Gặp (: đưa vào stack
Gặp số: ghi ra
Gặp phép toán:
Lấy và ghi ra tất cả các phép toán tại đỉnh của stack mà có
độ ưu tiên >= phép toán hiện tại
Đưa phép toán hiện tại vào stack
Gặp ):
Lấy và ghi ra tất cả các phép toán tại đỉnh cho đến khi gặp (
Lấy ( ra khỏi stack
Sau khi duyệt hết dãy thì lấy và ghi ra những gì còn trong stack
Độ ưu tiên
Bậc 2: *,/
Bậc 1: +, - Bậc 0: (,)
Trang 597 Chuyển từ trung tố sang hậu tố
Trang 618 Định trị biểu thức hậu tố
Gặp số: đưa vào stack
Gặp phép toán:
Lấy ra 1 số và gán vào a
Lấy ra 1 số và gán vào b
Thực hiện c=b <phép toán> a;
Đưa c vào stack
Sau khi duyệt hết thì lấy kết quả ra từ stack
Lưu ý thứ tự của
a, b, phép toán
Trang 63HẾT
Trang 649/11/2019 CTDL1- N.Đ.T.Nguyên 64
Kiểm tra điều kiện 45’
1 Hãy sắp xếp bằng phương pháp MergeSort (trộn tự
nhiên) dãy số sau