Ngăn xếp là một danh sách mà trong đó thao tác trên 1 phần tử vào trong ngăn xếp và thao tác lấy ra một phần tử được thực hiện 1 đầu. Các phần tử được đưa vào ngăn xếp sau cùng sẽ được[r]
(1)(2)2
NỘI DUNG CHƯƠNG 4
1 Khái niệm danh sách
2 Các phép toán danh sách Danh sách đặc
Định nghĩa
Biểu diễn danh sách đặc
Các thao tác danh sách đặc Ưu nhược điểm ứng dụng
4 Danh sách liên kết
Định nghĩa
Danh sách liên kết đơn Danh sách liên kết kép
Ưu nhược điểm danh sách liên kết
5 Danh sách hạn chế
Hàng đợi Ngăn xếp
(3)1 Khái niệm danh sách
Danh sách a
1, a2, ….aN tập hợp phần tử có
kiểu liệu xác định chúng có mối quan
hệ Nếu biết phần tử ai vị trí phần tử
ai+1
Số phần tử danh sách chiều dài
(4)4 2 Các phép toán danh sách
Tùy theo loại danh sách có phép tốn khác nhau, phép tốn thơng thường sau:
2.1 Tạo danh sách
Đưa vào danh sách nội dung phần tử Chiều dài danh sách xác định
2.2 Thêm phần tử vào danh sách
Khi thêm phần tử chiều dài danh sách tăng lên
Có thao tác thêm vào đầu, cuối hay vị trí xác định danh sách
2.3 Tìm kiếm phần tử danh sách
Tìm phần tử danh sách thỏa mãn điều kiện Dùng thuật tốn tìm kiếm chương “Tìm kiếm”
2.4 Loại bớt phần tử danh sách
Chiều dài danh sách giảm xuống phần tử
(5)2 Các phép toán danh sách (tt)
2.5 Sửa đổi giá trị phần tử danh sách
Thay đổi thông tin phần tử danh sách
Công việc cập nhật phần tử bao gồm thao tác tìm kiếm
ra phần tử cần hủy danh sách
2.6 Sắp xếp danh sách
Dùng thuật toán chương xếp
2.7 Tách danh sách thành nhiều danh sách con
Tách danh sách thành DS theo quy luật chia Tổng chiều dài danh sách chia chiều dài danh
sách ban đầu
2.8 Nhập nhiều danh sách thành danh sách
Nhập danh sách thành danh sách
(6)6 3 Danh sách đặc (Condensed List)
3.1 Định nghĩa
Danh sách đặc danh sách mà không gian nhớ lưu trữ
các phần tử nằm kề cận nhớ
3.2 Biểu diễn danh sách đặc
Biểu diễn danh sách đặc dùng 1mảng phần tử có kiểu dử
liệu kiểu liệu phần tử danh sách
Cần biết chiều dài tối đa danh sách đặc thông qua
biến
Cần biết chiều dài thực danh sách đặc thông qua
biến
VD:#define MaxLength 1000 int RealLength;
T CD_List[MaxLength]
(7)3 Danh sách đặc (tt)
3.3 Các thao tác danh sách đặc
Một số thao tác danh sách đặc thống kê tóm tắt: 3.3.1 Khởi tạo danh sách
Khởi tạo danh sách cho chiều dài danh sách trở void Khoitao(int &Len)
{
(8)8 3 Danh sách đặc (tt)
3.3 Các thao tác danh sách đặc (tt)
3.3.2 Tạo danh sách & nhập danh sách
Tạo danh sách có chiều dài tối đa MaxLen, hàm trả giá trị thực danh sách tạo
int TaoDanhSach(int M[], int &Len) {
if (Len > MaxLen) Len = MaxLen;
for (int I = 0; i< Len;I++) M[I] = Nhapphantu(); return (Len);
}
(9)3 Danh sách đặc (tt) 3.3 Các thao tác danh sách đặc (tt)
3.3.3 Thêm phần tử vào danh sách
Thêm phần tử có giá trị NewValue vào danh sách có chiều dài Length vị trí InsPos
B1: IF (Length = MaxLen) Thực BKT
B2: Pos = Length+1 B3: IF(Pos = InsPos)
Thực B7
B4: M[Pos] = M[Pos -1] B5:
(10)10 3 Danh sách đặc (tt)
3.3 Các thao tác danh sách đặc (tt)
3.3.3 Thêm phần tử vào danh sách (tt)
int Themphantu(int M[], int &Len, int x, int InsPos) {
if (Len == MaxLen) return (-1);
for (int I = Len; I >InsPos; I++) M[I] = M[I-1];
M[InsPos] = x; Len++;
(11)3 Danh sách đặc (tt)
3.3 Các thao tác danh sách đặc (tt)
3.3.4 Tìm kiếm phần tử danh sách
Dùng thuật toán tìm kiếm tìm phần tử thỏa mãn điều kiện danh sách
(12)12 3 Danh sách đặc (tt)
3.3 Các thao tác danh sách đặc (tt)
3.3.5 Hủy phần tử danh sách
Loại bỏ phần tử có vị trí DelPos danh sách M có chiều dài
Length (có thể có thao tác tìm kiếm xác định vị trí xóa phần tử) Thuật tốn:
B1: IF(Length =0 OR DelPos > Len) Thực BKT B2: Pos = DelPos
B3: IF(Pos = Length) Thực B7
B4: M[Pos] = M[Pos+1] B5: Pos++
(13)3 Danh sách đặc (tt)
3.3 Các thao tác danh sách đặc (tt)
3.3.5 Hủy phần tử danh sách (tt) int Xoaphantu(int M[], int &Len, int DelPos) {
int (Len ==0 || DelPos >=Len) return (-1);
for (int I =DelPos; i<Len; i++) M[i] = M[i+1];
Len ;
(14)14 3 Danh sách đặc (tt)
3.3 Các thao tác danh sách đặc (tt)
3.3.6 Sửa đổi giá trị cho phần tử danh sách
Giả sử phần tử danh sách thay đổi vị trí
Position danh sách M có chiều dài Length
Thao tác sửa đổi thao tác tìm kiếm phần tử cần có vị trí
(hay giá trị) gán giá trị
(15)3 Danh sách đặc (tt)
3.3 Các thao tác danh sách đặc (tt)
3.3.7 Sắp xếp thứ tự phần tử danh sách Dùng thuật toán xếp nội
Giải thuật xếp bọt (Bubble Sort)
Giải thuật sắp xếp dựa phân hoạch (Quick Sort)
Giải thuật xếp chọn trực tiếp (Straight Selection Sort) Giải thuật xếp chèn trực tiếp (Straight Insertion Sort) Giải thuật xếp trộn trực tiếp (Straight Merge Sort)
(16)16 3 Danh sách đặc (tt)
3.3 Các thao tác danh sách đặc (tt)
3.3.8 Tách danh sách thành nhiều danh sách
Có nhiều thao tác tách danh sách thành nhiều danh sách:
Phân phối luân phiên theo đường chạy (distribute)
Phân phối phần danh sách thành danh sách Tách phần tử thỏa mãn điều kiện cho trước thành
danh sách
Giả sử cần tách danh sách M có chiều dài Length thành danh sách SM1, SM2 có chiều dài tương ứng Slen1
(17)3 Danh sách đặc (tt)
3.3 Các thao tác danh sách đặc (tt)
3.3.8 Tách danh sách thành nhiều danh sách (tt) B1: IF(SLen1 >= Len)
SLen1 = Len SLen2 =
B2:IF(SLen2 >= Len) SLen2 = Len SLen1 =
B3: IF(SLen1 + SLen2 <> Len) SLen2 = Len – SLen1 B4: IF (SLen1 < 0) SLen1 =
B5: IF (SLen2 < 0) SLen2 = B6: I =1, SI =
B7: IF (I > SLen1) Thực B11 B8: SM[SI] = M[I]
(18)18 3 Danh sách đặc (tt)
3.3 Các thao tác danh sách đặc (tt)
3.3.8 Tách danh sách thành nhiều danh sách (tt)
void CS_Split(T M[], int Len, T SM1[], int &SLen1, T SM2[], int &SLen2) { if (Slen1 >=Len)
{ SLen1 = Len; Slen2 = 0; }
if (Slen2 >=Len) { SLen2 = Len;
SLen1 = 0; }
if (SLen1 < 0) SLen1 = 0; if (SLen2 < 0) SLen2 = 0;
if (SLen1 + SLen2 != Len) SLen2 = Len - SLen1; for (int i=0; i<SLen1; i++) SM1[i] = M[i];
for (int j=0; j<SLen2; i++, j++) SM2[j] = M[i]; return;
(19)3 Danh sách đặc (tt)
3.3 Các thao tác danh sách đặc (tt)
3.3.9 Nhập nhiều danh sách thành danh sách Các cách nhập danh sách:
Ghép nối đuôi danh sách thành danh sách có chiều
dài tổng chiều dài danh sách
Trộn xen kẽ phần tử danh sách theo quy luật
nào thành danh sách (dùng thuật toán merge merge sort)
Giả sử cần ghép danh sách SM1, SM2 có chiều dài SLen1,
(20)20 3 Danh sách đặc (tt)
3.3 Các thao tác danh sách đặc (tt)
3.3.9 Nhập nhiều danh sách thành danh sách(tt) Thuật toán:
B1: IF (Slen1+SLen2 > MaxLen) // M không đủ khả chứa
Thực BKT
B2: I = // Chép từ SM1[] vào M[]
B3: IF (I > SLen1) Thực B7 B4: M[I] = SM[I] B5: I++
B6: Lặp lại B3
B7: SI = // Chép từ SM2[] vào M[]
(21)3 Danh sách đặc (tt)
3.3 Các thao tác danh sách đặc (tt)
3.3.9 Nhập nhiều danh sách thành danh sách(tt)
int CD_Concat(T SM1[], int SLen1, T SM2[], int SLen2, T M [], int &Len)
{
if (SLen1+SLen2 > MaxLen) return (-1);
for (int I = 0; I < SLen1; I++) M[I] = SM1[I];
(22)22 3 Danh sách đặc (tt)
3.3 Các thao tác danh sách đặc (tt)
3.3.10 Sao chép danh sách: Sao chép nội dung danh sách thành danh sách khác có chiều dài
Thuật toán B1: I =
B2: IF (I > Length) // Length chiều dài dãy
B3: CM[I] = M[I] B4: I++
B5: Lặp lại B2 BKT: Kết thúc
int CD_Copy(T M[], int Len, T CM[]) // Hàm trả chiều dài DS
{ for (int i=0; i< Len; i++) CM[i] = M[i];
(23)3 Danh sách đặc (tt)
3.3 Các thao tác danh sách đặc (tt)
3.3.11 Hủy danh sách
Nếu danh sách cấp phát động dùng toán tử delete để
hủy
Nếu danh sách cấp phát tĩnh, việc hủy bỏ có tác
(24)24 3 Danh sách đặc (tt)
3.4 Ưu nhược điểm ứng dụng
Do phần tử lưu trữ kề cập với nhớ, danh
sách đặc có ưu điểm:
Mật độ sử dụng danh sách tối ưu tuyệt đối
Truy cập, tìm kiếm phần tử dễ dàng vị trí phần tử liền kề với nhớ
Nhược điểm danh sách thêm hay hủy phần tử
trong danh sách cần dịch chuyển phần tử cịn lại qua vị trí khác
Được ứng dụng nhiều cấu trúc liệu mảng (mảng
(25)4 Danh sách liên kết (Linked List) 4.1 Định nghĩa
(26)26
4 Danh sách liên kết (tt) 4.1 Định nghĩa
Danh sách liên kết tập hợp phần tử mà chúng có
một nối kết với thông qua vùng liên kết chúng
Tùy cách kết nối ràng buộc phần tử phần
tử khác, danh sách liên kết chia thành loại khác nhau: Danh sách liên kết đơn
Danh sách liên kết đôi/kép Danh sách đa liên kết
Danh sách liên kết vịng (vịng đơn, vịng đơi)
Mỗi loại danh sách có cách biểu diễn theo cấu trúc liệu
(27)4.2 Danh sách liên kết đơn (SLL)
4.2.1 Cấu trúc liệu
Nội dung phần tử (nút) danh sách liên kết gồm
vùng Vùng liệu và Vùng liên kết
struct Node { int info;
Node *pNext; // liên kết đến vùng phần tử
(28)28 4.2 Danh sách liên kết đơn (tt)
4.2.1 Cấu trúc liệu (tt)
Để quản lý danh sách liên kết dùng nhiều phương pháp
khác nhau, phương pháp có cấu trúc liệu cụ thể Quản lý địa phần đầu cuối danh sách
struct List {
Node *pHead; Node *pTail; };
info pNext pTail
(29)4.2 Danh sách liên kết đơn (tt)
4.2.2 Các thao tác danh sách liên kết đơn
a Khởi tạo danh sách SLL
b Tạo phần tử (nút) danh sách SLL c Thêm phần tử vào danh sách SLL
Thêm vào đầu | cuối | danh sách liên kết đơn
d Duyệt qua nút danh sách e Tìm kiếm phần tử danh sách f Hủy bỏ phần tử danh sách g Hủy danh sách
(30)30 4.2 Danh sách liên kết đơn (tt)
4.2.2.a Khởi tạo danh sách SLL
Thao tác khởi tạo danh sách liên kết đơn cho giá trị trỏ
quản lý địa đầu danh sách trỏ NULL
Hàm khởi tạo danh sách liên kết đơn:
void Khoitao(Node *pHead) {
pHead = NULL; return;
(31)4.2 Danh sách liên kết đơn (tt)
4.2.2 b Tạo phần tử (nút) danh sách SLL
Giả sử tạo phần tử có thành phần liệu =x
Thuật toán
B1: p = new Node //cấp phát nhớ cho trỏ p
B2: IF(p == NULL) // cấp phát không thành công
Thực BKT B3: p->info=x;
(32)32 4.2 Danh sách liên kết đơn (tt)
4.2.2 b Tạo phần tử (nút) danh sách SLL (tt) Cài đặt
Node* TaoPT(int x) { Node *p;
p=new Node; if (p==NULL)
{ cout<<"Khong du bo nho"; exit(1);
}
cout<<"\nMoi nhap vao so x = "; cin>>x;
p->Info=x;
p->pNext=NULL; return p;
(33)4.2 Danh sách liên kết đơn (tt)
4.2.2.c Thêm phần tử vào danh sách SLL (Thêm đầu DS) Thuật toán
Gỉa sử ta muốn thêm phần tử p vào đầu DS: Nếu DS rỗng thì:
pHead=p;
pTail=pHead; // pTail=new_element
Ngược lại:
(34)34 4.2 Danh sách liên kết đơn (tt)
4.2.2.c Thêm phần tử vào danh sách SLL (Thêm đầu DS) (tt) Cài đặt
void Themdau(List &l, Node *p) {
if (l.pHead==NULL) {
l.pHead=p; l.pTail=p; }
else
{ p->pNext=l.pHead; l.pHead=p;
(35)4.2 Danh sách liên kết đơn (tt)
4.2.2.c Thêm phần tử vào danh sách SLL (Thêm đầu DS) (tt)
x
pHead
pTail
(36)36 4.2 Danh sách liên kết đơn (tt)
4.2.2.c Thêm phần tử vào danh sách SLL (tt) (Thêm giữa DS)
Thêm phần tử vào sau phần tử q
Thuật toán
Nếu q!=NULL;
B1: p->pNext=q->pNext; B2: q->pNext=p
(37)4.2 Danh sách liên kết đơn (tt)
4.2.2.c Thêm phần tử vào danh sách SLL (Thêm DS) (tt) Cài đặt:
void Themgiua(List &l, Node *q, int x) {
Node *p=GetNode(x);
if (p==NULL) exit(1); if (q!=NULL)
{
p->pNext=q->pNext; q->pNext=p;
(38)38 4.2 Danh sách liên kết đơn (tt)
4.2.2.c Thêm phần tử vào danh sách SLL (Thêm cuối DS) Thuật toán:
Nếu DS rỗng thì: B1: pHead=p;
B2: pTail=pHead; Ngược lại:
(39)4.2 Danh sách liên kết đơn (tt)
4.2.2.c Thêm phần tử vào danh sách SLL (Thêm cuối DS) (tt) Cài đặt
void InsertTail(List &l, Node *p) {
if (l.pHead==NULL) { l.pHead=p;
l.pTail=p; }
(40)40 4.2 Danh sách liên kết đơn (tt)
4.2.2.d Duyệt qua nút danh sách liên kết đơn
Là thao tác thường dùng loại danh sách
Tùy theo trường hợp cụ thể để xử lý duyệt DS
Thuật toán: B1: p = pHead
B2: IF (p == NULL) Thực BKT
B3: OutputData(p->info) B4: p = p->pNext
(41)4.2 Danh sách liên kết đơn (tt)
4.2.2.d Duyệt qua nút danh sách liên kết đơn (tt) Cài đặt:
void DuyetDS(List l)
{ Node *p;
p = l.pHead;
while (p!=NULL) {
(42)42 4.2 Danh sách liên kết đơn (tt)
4.2.2.e Tìm kiếm phần tử danh sách
Giả sử cần tìm kiếm danh sách liên kết đơn phần tử có
phần liệu X
Dùng thuật tốn tìm tuyến tính
Thuật toán B1: p=pHead
B2: IF(p== NULL OR p->info == X) Thực BKT
(43)4.2 Danh sách liên kết đơn (tt)
4.2.2.e Tìm kiếm phần tử danh sách (tt) Cài đặt
Node* Timkiem(List l, int x)
{ Node *p;
p=l.pHead;
while ((p!=NULL) && (p->Info!=x)) p=p->pNext;
(44)44 4.2 Danh sách liên kết đơn (tt)
4.2.2.f Xoá phần tử danh sách
Xoá đầu DS
Thuật tốn:
Nếu (PHead !=NULL) thì: B1: p=pHead;
B2: pHead=pHead->pNext free(p);
(45)4.2 Danh sách liên kết đơn (tt)
4.2.2.f Xoá1 phần tử danh sách Xoá đầu DS
Cài đặt:
void Xoadau(List &l) // xoa phan tu {
p=new Node; p=l.pHead; if (p!=NULL)
{
(46)46 4.2 Danh sách liên kết đơn (tt)
4.2.2.f Xoá1 phần tử danh sách
Xoá phần tử sau phần tử q:
Thuật tốn:
nếu q!=NULL thì
B1: p=q->pNext; //p phần tử cần huỷ
B2: (p!=NULL) //q cuối DS B21: q->pNext=p->pNext;
(47)4.2 Danh sách liên kết đơn (tt)
4.2.2.f Xoá1 phần tử danh sách
Xoá phần tử sau phần tử q:
void XoaPT(List &l, Node *q) {
if (q!=NULL) {
p=q->pNext;// p la phan tu can xoa if (p!=NULL)
if(p==l.pTail)
{ l.pTail=q; free(p); }
(48)48 4.2 Danh sách liên kết đơn (tt)
4.2.2.f Xoá1 phần tử danh sách
Xố phần tử có khố k:
Thuật tốn:
B1: Tìm phần tử p có khố k phần tử q đứng trước nó
B2: Nếu (p!=NULL) //tìm thấy k Xố p khỏi DS
Ngược lại:
(49)4.2 Danh sách liên kết đơn (tt)
4.2.2.f Xoá1 phần tử danh sách
Xố phần tử có khố k:
Cài đặt:
int XoaptK(List &l,int k) // xoa phan tu {
Node *p=l.pHead; Node *q=NULL; while (p!=NULL)
{ if(p->info==k) break; q=p; p=p->pNext; }
(50)50 4.2 Danh sách liên kết đơn (tt)
4.2.2.f Xoá1 phần tử danh sách Xoá phần tử có khố k:
Cài đặt: (tt) else
{
l.pHead=p->pNext; if(l.pHead==NULL) l.pTail=NULL;
}
(51)4.2 Danh sách liên kết đơn (tt)
4.2.2.g Hủy danh sách
Việc hủy danh sách thực chất thực nhiều lần
hủy nút
Thuật toán:
B1: Trong DS chưa hết p=pHead;
pHead=pHead->pNext; B2: Huỷ p
(52)52 4.2 Danh sách liên kết đơn (tt)
4.2.2.g Hủy danh sách (tt) Cài đặt thuật toán:
void XoaDs (List &l) {
while (l.pHead!= NULL) {
p = l.pHead;
l.pHead = p->pNext; delete (p);
}
(53)4.2 Danh sách liên kết đơn (tt)
4.2.2.h Tạo danh sách/Nhập danh sách
Tạo danh sách thực chất liên tục thêm phần tử vào
danh sách mà danh sách ban đầu rỗng
Tạo DS cách thêm vào đầu DS
void TaoDSdau(List &l, int x) {
for (int i=0;i<8;i++) // nen dung vong lap while de viet {
TaoPT(x);
(54)54 4.2 Danh sách liên kết đơn (tt)
Tạo DS cách thêm vào cuối DS
void TaoDScuoi(List &l, int x) {
for (int i=0;i<1;i++) {
TaoPT(x);
Themcuoi(l,p); }
(55)4.2 Danh sách liên kết đơn (tt)
(56)56 4.2 Danh sách liên kết đơn (tt)
(57)4.2 Danh sách liên kết đơn (tt)
4.2.2.k Sắp xếp thứ tự phần tử danh sách Thuật toán xếp trộn tự nhiên:
B1: IF (SLLSplit(SLList, TempList) == NULL) Thực BKT B2: SLLMerge(SLList, TempList, SLList)
B3: Lặp lại B1 BKT: Kết thúc
void SLLNaturalMergeSort(SLLType &SList) { SLLType TempList = NULL, List = NULL;
(58)58 4.2 Danh sách liên kết đơn (tt)
4.2.2.h Sao chép danh sách
Sao chép danh sách thực chất tạo danh sách
NewList cách duyệt qua nút SLList để lấy thành phần liệu để tạo thành nút & bổ sung nút vào danh sách NewList
Thuật toán
B1: NewList = NULL B2: CurrNode = SLList
B3: IF (CurNode = NULL) Thực BKT B4: SLLAddLast(NewList, CurrNode->Key) B5: CurrNode = CurrNode->NextNode
(59)4.2 Danh sách liên kết đơn (tt)
4.2.2.h Sao chép danh sách (tt) Cài đặt thuật toán:
SLLType SLLCopy(SLLType SList, SLLType &NewList) { NewList = NULL;
SLLType CurrNode = SList; while (CurrNode != NULL)
{ SLLType NewNode=SLLAddLast(NewList,CurrNode->Key); if (NewNode == NULL)
(60)60 4.3 Danh sách liên kết đôi (DLL)
Các phần tử danh sách liên kết đơi có mối liên kết với
các phần tử khác danh sách
Cấu trúc liệu danh sách liên kết đôi:
typedef struct DLLNode { T Key;
InfoType Info;
DLLNode * NextNode; DLLNode * PreNode; } DLLOneNode;
typedef struct DLLNode { T Key;
DLLNode * NextNode; DLLNode * PreNode; } DLLOneNode;
(61)4.3 Danh sách liên kết đôi (tt) 4.3.1 Quản lý danh sách liên kết liên kết đôi:
Quản lý địa phần tử đầu danh sách
DLLType DLList1
Quản lý địa phần tử đầu phần tử cuối danh sách
typedef struct DLLPairNode { DLLType DLLFirst;
DLLType DLLLast; } DLLPType;
DLLPType DLList2;
Quản lý địa phần tử đầu, phần tử cuối số phần tử
danh sách
(62)62 4.3 Danh sách liên kết đôi (tt)
4.3.2 Thao tác danh sách liên kết đôi
a Khởi tạo danh sách liên kết đôi b Tạo phần tử
c Thêm phần tử vào danh sách
d Duyệt qua nút danh sách e Tìm kiếm phần tử danh sách f Loại bỏ phần tử danh sách g Hủy toàn danh sách
h Tạo danh sách mới/Nhập danh sách i Tách danh sách thành nhiều danh sách j Nhập nhiều danh sách thành danh sách
(63)4.3 Danh sách liên kết đôi (tt) 4.3.2.a Khởi tạo danh sách liên kết đôi
Cho giá trị trỏ quản lý địa nút đầu cuối danh sách liên kết đôi NULL
DLLPType DLLInitialize(DLLPType &DList) {
DList.DLLFirst = NULL; DList.DLLast = NULL; return (DList);
(64)64 4.3 Danh sách liên kết đôi (tt)
4.3.2.b Tạo phần tử
Tạo nút có thành phần liệu NewData Thuật toán
B1: Dnode = New DLLOneNode B2: IF (Dnode == NULL)
Thực BKT
B3: DNode ->NextNode = NULL B4: DNode ->Key = NewData B5: DNode ->PreNode = NULL BKT: Kết thúc
DLLType DLLCreateNode(T NewData) { DLLType Pnode = new DLLOneNode;
if (Pnode != NULL)
{ Pnode ->NextNode = NULL; Pnode ->Key = NewData
Pnode ->PreNode = NULL; }
(65)4.3 Danh sách liên kết đôi (tt) 4.3.2.c Thêm phần tử vào danh sách (Thêm đầu) B1: NewNode = DLLCreateNode(NewData)
B2: IF (NewNode == NULL) Thực BKT
B3: IF(DLLList.DLLFirst == NULL)
B3.1: DLLList.DLLFirst = NewNode B3.2: DLLList.DLLLast = NewNode B3.3: Thực BKT
B4: NewNode ->NextNode = DLLList.DLLFirst B5: DLLList.DLLFirst ->PreNode = NewNode
(66)66 4.3 Danh sách liên kết đôi (tt)
4.3.2.c Thêm phần tử vào danh sách (Thêm đầu) DLLType DLLAddFirst(DLLPType &DList, T NewData) {
DLLType NewNode = DLLCreateNode(NewData); if (NewNode == NULL)
return (NULL);
if (DList.DLLFirst == NULL)
DList.DLLFirst = DList.DLLLast = NewNode; else
{
NewNode ->NextNode = DList.DLLFirst; DList.DLLFirst ->PreNode = NewNode; DList.DLLFirst = NewNode;
}
(67)4.3 Danh sách liên kết đôi (tt) 4.3.2.c Thêm phần tử vào danh sách (Thêm cuối) B1: NewNode = DLLCreateNode(NewData)
B2: IF (NewNode == NULL) Thực BKT
B3: IF(DLLList.DLLFirst == NULL)
B3.1: DLLList.DLLFirst = NewNode B3.2: DLLList.DLLLast = NewNode B3.3: Thực BKT
B4: DLLList.DLLLast ->NextNode = NewNode B5: NewNode ->PreNode = DLLList.DLLLast
(68)68 4.3 Danh sách liên kết đôi (tt)
4.3.2.c Thêm phần tử vào danh sách (Thêm cuối) DLLType DLLAddLast(DLLPType &DList, T NewData) {
DLLType NewNode = DLLCreateNode(NewData); if (NewNode == NULL)
return (NULL);
if (DList.DLLLast == NULL)
DList.DLLFirst = DList.DLLLast = NewNode; else
{
DList.DLLLast ->NextNode = NewNode; NewNode ->PreNode = DList.DLLLast; DList.DLLLast = NewNode;
}
(69)4.3 Danh sách liên kết đôi (tt) 4.3.2.c Thêm phần tử vào danh sách (Thêm giữa) B1: IF (InsNode ->NextNode == NULL)
B1.1: DLLAddLast(DLLList, NewData) B1.2: Thực BKT
B2: NewNode = DLLCreateNode(NewData) B3: IF (NewNode == NULL)
Thực BKT
(70)70 4.3 Danh sách liên kết đôi (tt)
4.3.2.c Thêm phần tử vào danh sách (Thêm giữa)
DLLType DLLAddMid(DLLPType &DList, T NewData, DLLType &InsNode)
{ DLLType NewNode = DLLCreateNode(NewData); if (NewNode == NULL)
return (NULL);
if (InsNode ->NextNode == NULL)
{ InsNode ->NextNode = NewNode; NewNode ->PreNode = InsNode; DList.DLLLast = NewNode;
} else
{ NewNode ->NextNode = InsNode ->NextNode; InsNode ->NextNode ->PreNode = NewNode; InsNode ->NextNode = NewNode;
NewNode ->PreNode = InsNode; }
(71)4.3 Danh sách liên kết đôi (tt) 4.3.2.d Duyệt qua nút danh sách
Thuật toán
B1: CurrNode = DLLList.First B2: IF (CurrNode == NULL)
Thực BKT
B3: OutputData(CurrNode->Key)
B4: CurrNode = CurrNode ->NextNode B5: Lặp lại B2
BKT: Kết thúc
Cài đặt thuật toán
void DLLTravelling (DLLPType DList) { DLLType CurrNode = DList.DLLFirst;
(72)72 4.3 Danh sách liên kết đơi (tt)
4.3.2.e Tìm kiếm phần tử danh sách Thuật toán
B1: CurrNode = DLLList.First
B2: IF (CurrNode == NULL OR CurrNode->Key = SearchData) Thực BKT
B3: CurrNode = CurrNode ->NextNode B4: Lặp lại B2
BKT: Kết thúc
Cài đặt thuật toán
DLLType DLLSearching(DLLPType Dlist, T SearchData) { DLLType CurrNode = DList.DLLFirst;
while (CurrNode != NULL)
{ if (CurrNode->Key == SearchData) break;
CurrNode = CurrNode ->NextNode }
(73)4.3 Danh sách liên kết đôi (tt) 4.3.2.f Loại bỏ phần tử danh sách
Thuật toán
B1: DelNode = DLLSearching(DLLList DelData) // Tìm kiếm nút DelData B2: IF(DelNode == NULL)
Thực BKT
B3: IF(DelNode->PreNode=NULL AND DelNode->NextNode=NULL) B3.1: DLLList.DLLFirst = DLLList.DLLLast = NULL
B3.2: Thực B8
B4: IF (DelNode ->PreNode = NULL) // Loại nút DS B4.1: DLLList.DLLFirst = DLLList.DLLFirst ->NextNode
B4.2: DLLList.DLLFirst ->PreNode = NULL B4.3: Thực B8
B5: IF (DelNode ->NextNode = NULL) // Loại nút cuối DS B4.1: DLLList.DLLLast = DLLList.DLLLast ->PreNode B4.2: DLLList.DLLLast ->NextNode = NULL
(74)74 4.3 Danh sách liên kết đôi (tt)
4.3.2.f Loại bỏ phần tử danh sách Cài đặt thuật toán
Int DLLDeleteNode (DLLPType &DList, T DelData)
{ DLLType DelNode = DLLSearching(DList, DelData) if (DelNode == NULL)
return (-1);
if (DelNode ->NextNode == NULL && DelNode ->PreNode == NULL) DList.DLLFirst = DList.DLLLast = NULL;
else
if (DelNode ->PreNode ==NULL)
{ DList.DLLFirst = Dist.DLLFirst ->NextNode ; Dist.DLLFirst ->PreNode = NULL;
} else
if (DelNode ->NextNode ==NULL)
{ DList.DLLLast = Dist.DLLLast ->PreNode ; Dist.DLLLast ->NextNode = NULL;
} else
{ DelNode ->PreNode ->NextNode = DelNode ->NextNode; DelNode ->NextNode ->PreNode = DelNode ->PreNode ; }
(75)4.3 Danh sách liên kết đơi (tt) 4.3.2.g Hủy tồn danh sách
Thực nhiều lần thao tác hủy nút Thuật toán
B1: IF (DLLList.DLLFirst == NULL) Thực BKT
B2: TempNode = DLLList.DLLFirst
B3: DLLList.DLLFirst = DLLList.DLLFirst ->NextNode B4: IF (DLLList.DLLFirst == NULL)
B4.1: DLLList.DLLLast = NULL B4.2: Thực B7
(76)76 4.3 Danh sách liên kết đơi (tt)
4.3.2.g Hủy tồn danh sách (tt) Cài đặt thuật toán
void DLLDelete (DLLPType &DList) {
DLLType TempNode = DList.DLLFirst; while (TempNode != NULL)
{
DList.DLLFirst = DList.DLLFirst ->NextNode; TempNode ->NextNode = NULL;
if (DList.DLLFirst != NULL)
DList.DLLFirst ->PreNode = NULL; delete TempNode;
TempNode = DList.DLLFirst; }
(77)4.3 Danh sách liên kết đôi (tt) 4.3.2.h Tạo danh sách mới/Nhập danh sách
Thuật toán
B1: DLLInitialize(DLLList) B2: I =
B3: IF (I >N)
Thực BKT
B4: NewData = InputNewData();
B5: DLLAddLast(DLLList, NewData) B6: I++
(78)78 4.3 Danh sách liên kết đôi (tt)
4.3.2.h Tạo danh sách mới/Nhập danh sách Cài đặt thuật toán
DLLPType DLLCreate (DLLPType &DList, int N) {
DLLInitialize(DList); T NewData;
for (int i=0; i <N; i++) {
NewData = InputNewData();
if (DLLAddLast(DList, NewData) == NULL) { DLLDelete(DList);
break; }
}
(79)(80)80 4.3 Danh sách liên kết đôi (tt)
(81)4.3 Danh sách liên kết đôi (tt)
4.3.2.k Sắp xếp thứ tự thành phần liệu danh sách B1: Inode = DLLList.DLLFirst
B2: IF(Inode == NULL) Thực BKT
B3: IF (Inode == DLLList.DLLLast) Thực BKT
B4: Jnode = DLLList.DLLLast B5: IF (Jnode = Inode)
Thực B7 B6: ELSE
(82)82 4.3 Danh sách liên kết đôi (tt)
4.3.2.k Sắp xếp thứ tự thành phần liệu danh sách (tt) Cài đặt thuật toán
void DLLBubbleSort (DLLPType &DList) { DLLType Inode = DList.DLLFirst;
if (Inode == NULL) return;
while (Inode != DList.DLLLast)
{ DLLType Jnode = DList.DLLLast; while (Jnode != Inode)
{ if (Jnode->Key < Jnode ->PreNode ->Key)
Swap(Jnode->Key,Jnode->PreNode->Key) Jnode = Jnode ->PreNode ;
}
Inode = Inode ->NextNode ; }
(83)4.3 Danh sách liên kết đôi (tt) 4.3.2.l Sao chép danh sách thành danh sách Thuật toán
B1: DLLInitialize(NewList)
B2: CurrNode = DLLList.DLLFirst B3: IF (CurrNode == NULL)
Thực BKT
B4: DLLAddLast(NewList, CurrNode->Key) B5: CurrNode = CurrNode ->NextNode
(84)84 4.3 Danh sách liên kết đôi (tt)
4.3.2.l Sao chép danh sách thành danh sách Cài đặt thuật toán
DLLPType DLLCopy(DLLPType &DList, DLLPType &NewList) {
DLLInitialize(NewList);
DLLType CurrNode = DList.DLLFirst; while (CurrNode != NULL)
{
if (DLLAddLast(NewList, CurrNode->Key) == NULL) { DLLDelete(NewList);
break; }
CurrNode = CurrNode ->NextNode ; }
(85)4 Danh sách liên kết
4.4 Ưu nhược điểm danh sách liên kết
Nhược điểm
Mật độ sử dụng nhớ danh sách liên kết không tối ưu tuyệt đối (<100%)
Việc truy xuất tìm kiếm phần tử danh sách liên kết nhiều thời gian phải duyệt qua phần tử danh sách
Bộ nhớ cần nhiều phải lưu thêm phần tử liên kết, vùng liệu lớn tỷ lệ mức sử dụng nhớ cao
Ưu điểm
(86)86 5 Danh sách hạn chế
5.1 Hàng đợi (Queue) 5.2 Ngăn xếp (Stack)
(87)5 Danh sách hạn chế
5.1 Hàng đợi (Queue)
Hàng đợi danh sách mà thao tác thêm phần
tử vào danh sách thực đầu lấy phần tử danh sách lại thực đầu
Các phần tử đưa vào hàng đợi trước lấy
trước, phần tử đưa vào hàng đợi sau lấy sau
Hàng đợi gọi danh sách FIFO List cấu trúc
liệu gọi cấu trúc FIFO (First In First Out)
Có nhiều cách biểu diễn hàng đợi: dùng danh sách đặc
(88)88 5.1 Hàng đợi (tt)
5.1.1 Cấu trúc liệu biểu diễn cho hàng đợi
Biểu diễn tổ chức hàng đợi danh sách đặc danh
sách liên kết đơn quản lý phần tử đầu cuối
Cấu trúc liệu biểu diễn hàng đợi danh sách đặc
typedef struct QC { int Len;
int Front, Rear; T * List;
} CQUEUE;
(89)5.1 Hàng đợi (tt)
5.1.1 Cấu trúc liệu biểu diễn cho hàng đợi (tt)
Cấu trúc liệu biểu diễn hàng đợi danh sách liên kết typedef struct QElement
{ T Key;
QElement *Next; } QOneElement;
typedef QElement *QType; typedef struct QPElement { QType Font;
(90)90 5.1 Hàng đợi (tt)
5.1.2 Các thao tác hàng đợi tổ chức danh sách đặc
a Khởi tạo hàng đợi (Initialize)
b Thêm phần tử vào hàng đợi (Add)
(91)5.1 Hàng đợi (tt)
5.1.2.a Khởi tạo hàng đợi (tổ chức danh sách đặc)
B1: CQList.Len = Length
B2: CQList.List = new T[Length] B3: IF(CQList.List == NULL)
Thực BKT
(92)92 5.1 Hàng đợi (tt)
5.1.2.a Khởi tạo hàng đợi (tổ chức danh sách đặc)
Cài đặt thuật toán
T * CQInitialize (CQUEUE & QList, int Length) {
QList.Len = Length;
QList.List = new T[Length]; if (QList.List == NULL)
return (NULL);
QList.Front = QList.Rear =-1; return (QList.List);
(93)5.1 Hàng đợi (tt)
5.1.2.b Thêm phần tử vào hàng đợi (tổ chức danh sách đặc)
Thuật toán
// hàng đợi bị đầy
B1: IF(CQList.Front ==1 AND CQList.Rear == CQList.Len) Thực BKT
B2: IF(CQList.Rear+1 == CQList.Front) Thực BKT
B3: IF(CQList.Front = 0) // hàng đợi rỗng CQList.Front =
B4: IF(CQList.Rear = CQList.Len) CQList.Rear =
(94)94 5.1 Hàng đợi (tt)
5.1.2.b Thêm phần tử vào hàng đợi (tổ chức danh sách đặc)
Cài đặt thuật toán
int CQAdd(CQUEUE & QList, T NewData)
{ if (QList.Front == && QList.Rear == QList.Len -1) return (-1);
if (QList.Rear +1 == QList.Front) return (-1);
if (QList.Front == -1) QList.Front =0
if (QList.Rear == QList.Len) QList.Rear = 0;
else
QList.Rear += 1;
QList.List[QList.Rear] = NewData return (QList.Rear );
(95)5.1 Hàng đợi (tt)
5.1.2.c Lấy nội dung phần tử hàng đợi xử lý (tổ chức danh sách đặc)
B1: IF (CQList.Front = 0) Thực BKT
B2: Data = CQList.List[CQList.Front] B3: IF(CQList.Rear == CQList.Front)
B3.1: CQList.Rear = CQList.Front = B3.2: Thực BKT
B4: IF (CQList.Front = CQList.Len) CQList.Front =
(96)96 5.1 Hàng đợi (tt)
5.1.2.c Lấy nội dung phần tử hàng đợi xử lý (tổ chức
danh sách đặc)
Cài đặt thuật toán
int CQGet(CQUEUE & QList, T &Data)
{ if (QList.Front == -1)
return (-1);
Data = QList.List[QList.Front]; if (QList.Front == QList.Rear) { QList.Front = QList.Rear = -1; return (1);
}
if (QList.Front == QList.Len -1) QList.Front = 0;
else
QList.Front += 1; return (1);
(97)5.1 Hàng đợi (tt)
5.1.2.d Hủy hàng đợi (tổ chức danh sách đặc)
Hủy nhớ cấp phát cho hàng đợi void CQDelete(CQUEUE & QList) {
delete QList.List; return;
(98)98 5.1 Hàng đợi (tt)
5.1.3 Các thao tác hàng đợi tổ chức danh sách liên kết đơn
a Khởi tạo hàng đợi (Initialize)
b Thêm phần tử vào hàng đợi (Add)
(99)5.1 Hàng đợi (tt)
5.1.3.a Khởi tạo hàng đợi (dùng danh sách liên kết đơn)
Tương tự với danh sách liên kết đơn, hàm khởi tạo thực gán trỏ Front Rear NULL
SQUEUE SQInitialize (SQUEUE &QList) {
QList.Front = QList.Rear = NULL; return (QList);
(100)100 5.1 Hàng đợi (tt)
5.1.3.b Thêm phần tử vào hàng đợi (dùng danh sách liên kết đơn)
Thêm phần tử vào sau phần tử Rear (Thêm vào cuối danh sách liên kết)
Giả sử liệu đưa vào hàng đợi NewData B1: NewElement = SLLCreateNode(NewData) B2: IF (NewElement == NULL)
Thực BKT
B3: IF (SQList.Front == NULL) // hàng đợi dang rỗng B3.1: SQList.Front = SQList.Rear = NewElement B3.2: Thực BKT
B4: SQList.Rear->Next = NewElement B5: SQList.Rear = NewElement
(101)5.1 Hàng đợi (tt)
5.1.3.b Thêm phần tử vào hàng đợi (dùng danh sách liên kết đơn)
Cài đặt thuật toán:
QType SQAdd(SQUEUE &Qlist, T NewData)
{ QType NewElement = SLLCreateNode(NewData) if (NewElement == NULL)
return (NULL);
if (QList.Front == NULL)
QList.Front = QList.Rear = NewElement; else
(102)102 5.1 Hàng đợi (tt)
5.1.3.c Lấy nội dung phần tử hàng đợi xử lý (dùng
danh sách liên kết đơn)
Lấy nội dung thành phần liệu phần tử địa Front biến Data tiến hành hủy phần tử
B1: IF (SQList.Front == NULL) // hàng đợi bị rỗng Thực BKT
B2: TempElement = SQList.Front;
B3: SQList.Front = SQList.Front ->Next B4: TempElement ->Next = NULL
B5: Data = TempElement ->Key B6: IF (SQList.Front == NULL)
(103)5.1 Hàng đợi (tt)
5.1.3.c Lấy nội dung phần tử hàng đợi xử lý (dùng danh sách liên kết đơn) Cài đặt thuật toán
int SQGet (SQUEUE &QList, T &Data) { if (QList.Front = NULL)
return (-1);
QType TempElement = QList.Front; QList.Front = QList.Front ->Next; TempElement ->Next = NULL; Data = TempElement ->Next ; if (QList.Front = NULL)
(104)104 5.1 Hàng đợi (tt)
5.1.3.d Hủy hàng đợi (dùng danh sách liên kết đơn)
void SQQueue (SQUEUE &QList) {
QList.Rear = NULL;
while (QList.Front != NULL) {
QType TempElement = QList.Front; TempElement ->Next = NULL;
delete TempElement; }
(105)5.2 Ngăn xếp (Stack)
Ngăn xếp danh sách mà thao tác phần tử vào ngăn xếp thao tác lấy phần tử thực đầu
Các phần tử đưa vào ngăn xếp sau lấy trước tiên, phần tử đưa vào trước tiên lấy sau
Ngăn xếp gọi danh sách vào sau trước LIFO, cấu trúc liệu gọi cấu trúc LIFO
5.2.1 Cấu trúc liệu
(106)106 5.2 Ngăn xếp (tt)
5.2.1 Cấu trúc liệu
Biểu diễn tổ chức danh sách đặc typedef struct SC
{ int Size; int SP; T * List; } CSTACK;
CSTACK CSList;
Biểu diễn tổ chức danh sách liên kết typedef struct SElement
{ T Key;
SElement *Next;
} SOneElement;
(107)5.2 Ngăn xếp (tt)
5.2.2 Các thao tác ngăn xếp tổ chức danh sách đặc 5.2.2.a Khởi tạo ngăn xếp (Initialize)
5.2.2.b Thêm phần tử vào ngăn xếp (Push)
(108)108 5.2 Ngăn xếp (tt)
5.2.2.a Khởi tạo ngăn xếp (dùng danh sách đặc)
B1: CSList.Size = MaxSize
B2: CSList.List = new T[MaxSize] B3: IF (CSList.List == NULL)
Thực BKT
B4: CSList.SP = CSList.Size +1 BKT: Kết thúc
T * CSInitialize(CSTACK &SList, int MaxSize) { SList.Size = MaxSize;
SList.List = new T[MaxSize]; if (SList.List == NULL)
return (NULL);
SList.SP = SList.Size ; return (SList.List);
(109)5.2 Ngăn xếp (tt)
5.2.2.b Thêm phần tử vào ngăn xếp (dùng danh sách đặc)
B1: IF (CSList.SP == 1) Thực BKT
B2: CSList.SP
B3: CSList.List[CSList.SP] = NewData BKT: Kết thúc
int CSPush(CSTACK &SList, T NewData) { if (SList.SP == 0)
(110)110 5.2 Ngăn xếp (tt)
5.2.2.c Lấy nội dung phần tử ngăn xếp xử lý (dùng danh sách đặc)
B1: IF (CSList.SP == CSList.Size +!) Thực BKT
B2: Data = CSList.List[CSList.SP] B3: CSList.SP++
BKT: Kết thúc
int CSPop(CSTACK &SList, T &Data) { if (SList.SP == SList.Size)
return (-1);
Data = SList.List[SList.SP]; SList.SP += 1;
(111)5.2 Ngăn xếp (tt)
5.2.2.d Hủy ngăn xếp (dùng danh sách đặc)
int CSDelete(CSTACK &SList) {
delete SList.SList; return;
(112)112 5.2 Ngăn xếp (tt)
5.2.2 Các thao tác ngăn xếp tổ chức danh sách liên kết 5.2.3.a Khởi tạo ngăn xếp (Initialize)
5.2.3.b Thêm phần tử vào ngăn xếp (Push)
(113)5.2 Ngăn xếp (tt)
5.2.3.a Khởi tạo ngăn xếp (dùng danh sách liên kết)
SSTACK SSInitialize (SSTACK &SList) { SList = NULL;
(114)114 5.2 Ngăn xếp (tt)
5.2.3.b Thêm phần tử vào ngăn xếp (dùng danh sách liên kết)
B1: NewElement = SLLCreateNode(NewData) B2: if (NewElement == NULL)
Thực BKT B3: if (SSP == NULL)
B3.1: SSP = NewElement B3.2: Thực BKT
B4: NewElement ->Next = SSP B5: SSP = NewElement
(115)5.2 Ngăn xếp (tt)
5.2.3.b Thêm phần tử vào ngăn xếp (dùng danh sách liên kết)
SSTACK SSPush (SSTACK &SList, T NewData)
{ SSTACK NewElement = SLLCreateNode(NewData); if (NewElement == NULL)
return (NULL);
NewElement ->Next = SList; SList = NewElement;
(116)116 5.2 Ngăn xếp (tt)
5.2.3.c Lấy nội dung phần tử ngăn xếp xử lý (dùng danh sách liên kết)
B1: if (SSP == NULL) Thực BKT
B2: TempElement = SSP B3: SSP = SSP ->Next
B4: TempElement ->Next = NULL B5: Data = TempElement->Key B6: delete
(117)5.2 Ngăn xếp (tt)
5.2.3.c Lấy nội dung phần tử ngăn xếp xử lý (dùng danh sách liên kết)
int SSPop (SSTACK &SList, T &Data) {
if (SList == NULL) return (-1);
SSTACK TempElement = SList; SList = SList ->Next;
(118)118 5.2 Ngăn xếp (tt)
5.2.3.d Hủy ngăn xếp (dùng danh sách liên kết)
void SSDelete (SSTACK &SList) {
while (SList != NULL)
{ SSTACK TempElement = SList; SList = SList ->Next;
TempElement ->Next = NULL; delete TempElement;
(119)5.2 Ngăn xếp (tt)
5.3 Ứng dụng danh sách hạn chế
Hàng đợi dùng nhiều trường hợp lưu trữ liệu cần xử
lý
Ngăn xếp dùng việc xử lý liệu truy hồi, đặc biệt
(120)120 BÀI TẬP CHƯƠNG 4
Bài tập chương 4, giáo trình Cấu trúc liệu giải thuật