• Chèn phần tử vào SAU phần tử q cho trước trong danh sách.. • Chèn phần tử vào TRƯỚC phần tử q cho trước trong danh sách.. • Hủy phần tử vào SAU phần tử q cho trước trong danh sách.. •
Trang 11
DÁNH SÁCH LIÊN KẾT KÉP
1 ĐỊNH NGHĨA danh sách liên kết đơn
2 Hàm KHỞI TẠO danh sách rỗng
3 Hàm kiểm tra có phải danh sách RỖNG
4 Tạo một NÚT có thành phần dữ liệu là x
5 Chèn một phần tử vào danh sách
• Chèn phần tử vào ĐẦU danh sách
• Chèn phần tử vào CUỐI danh sách
• Chèn phần tử vào SAU phần tử q cho trước trong danh sách
• Chèn phần tử vào TRƯỚC phần tử q cho trước trong danh sách
6 Hủy một phần tử trong danh sách
• Hủy phần tử ĐẦU danh sách
• Hủy phần tử CUỐI danh sách
• Hủy một phần tử có KHÓA x
• Hủy phần tử vào SAU phần tử q cho trước trong danh sách
• Hủy phần tử vào TRƯỚC phần tử q cho trước trong danh sách
7 Duyệt danh sách
8 Tìm một phần tử trong danh sách theo một điều kiện cho trước
9 Sắp xếp danh sách
Trang 22
❖
❖
1 ĐỊNH NGHĨA danh sách liên kết kép
pTail Node
List
pHead
• Danh sách liên kết kép là: danh sách mà mỗi phần tử trong danh sách liên kết với các phần tử đứng trước và sau nó bằng hai mối liên kết
Ví dụ 1: Khai báo cấu trúc danh sach liên kết kép các SOTHUC
BG:
//Cấu trúc của một nút struct Node
{
float Info; //KDL Info;
struct Node*pNext;
struct Node*pPrev;
};
typedef struct Node DNODE;
//Cấu trúc DSLK kép struct List
{
DNODE *pHead;
DNODE *pTail;
};
typedef struct List DLIST;
Trang 33
Ví dụ 2: Khai báo cấu trúc danh sach liên kết kép PHANSO
BG:
struct PhanSo {
int Tu;
int Mau;
};
typedef struct PhanSo PS;
struct Node {
PS Info; //KDL Info;
struct Node*pNext;
struct Node*pPrev;
};
typedef struct Node DNODE;
struct List {
DNODE *pHead;
DNODE *pTail;
};
typedef struct List DLIST;
Ví dụ 3: Khai báo cấu trúc danh sach liên kết kép các điểm tọa độ
trong mặt phẳng Oxy
BG:
struct Diem {
float x;
float y;
};
typedef struct Diem DIEM;
struct Node {
DIEM Info; //KDL Info;
struct Node*pNext;
struct Node*pPrev;
};
typedef struct Node DNODE;
Trang 44
struct List {
DNODE *pHead;
DNODE *pTail;
};
typedef struct List DLIST;
2 Hàm KHỞI TẠO danh sách rỗng
Thao tác thực hiện: Thao tác này sẽ khởi tạo một danh sách kép rỗng ban đầu Địa chỉ nút đầu với nút cuối đều là NULL
void Create_DList(DLIST &l) {
l.pHead = NULL;
l.pTail = NULL;
}
3 Hàm kiểm tra có phải danh sách RỖNG
int IsEmpty_D(DLIST l) {
if (l.pHead == NULL)
return 1;
return 0;
}
4 Tạo một NÚT có thành phần dữ liệu là x
o Thao tác thực hiện: Thao tác này sẽ tạo một phần tử mới và gán thành phần dữ liệu là x, chuẩn bị cho thao tác thêm phần
tử vào danh sách Hàm trả về địa chỉ phần tử mới
o Thuật toán
Nếu(p != NULL) + p->Info = x;
+ p->Next;
+ p->Pre = NULL;
+return p;
Trang 55
o Hàm
DNODE* CreatDNode(int x) {
DNODE *p = new DNODE;
if (p == NULL)
return NULL;
p->Info = x;
p->pNext = NULL;
p->pPrev = NULL;
return p;
}
DNODE* CreatDNode(int x) {
DNODE *p = new DNODE;
if (p == NULL)
return NULL;
else {
p->Info = x;
p->pNext = NULL;
p->pPrev = NULL;
return p;
} }
5 Chèn một phần tử vào danh sách
• Chèn phần tử vào ĐẦU danh sách
P
pHead
pTail
• Thuật toán Nếu danh sách rỗng thì + Head = p;
+Tail = Head;
Ngược lại
Trang 66
+ p->Next = Head;
+Head->Prev = p;
+Head = p;
• Hàm chèn một phần tử vào đầu danh sách AddHead
void AddDHead(DLIST &l, DNODE*p) {
if (l.pHead == NULL) {
l.pHead = p;
l.pTail = l.pHead;
} else {
p->pNext = l.pHead;
l.pHead->pPrev = p;
l.pHead = p;
} }
• Chèn phần tử vào CUỐI danh sách
pTail
P A
• Thuật toán :
+Nếu danh sách rỗng thì : Head = p;
Tail = Head;
+Ngược lại : p->Prev = Tail;
Tail->Next=p;;
Trang 77
Tail = p;
• Hàm chèn một phần tử vào cuối danh sách AddTail
void AddDEnd(DLIST &l, DNODE*p) {
if (l.pHead == NULL) {
l.pHead = p;
l.pTail = l.pHead;
} else {
p->pPrev = l.pTail;
l.pTail->pNext = p;
l.pTail = p;
} }
• Chèn phần tử vào SAU phần tử q cho trước trong danh sách
P
• Hàm Chèn phần tử vào SAU phần tử q cho trước trong danh sách
void AddLastQ(DLIST &l, DNODE *Tam, DNODE *q) {
DNODE *p;
p = q->pNext;
if (q != NULL)//them vao duoc {
Trang 88
Tam->pNext = p;
Tam->pPrev = q;
q->pNext = Tam;
if (p != NULL)
p->pPrev = Tam;
if (q == l.pTail) //them vao sau danh sach lien ket
l.pTail = Tam;
} else
AddDHead(l, Tam);
}
• Chèn phần tử vào TRƯỚC phần tử q cho trước trong danh sách
P
• Hàm Chèn phần tử vào TRƯỚC phần tử q cho trước trong danh sách
void AddBeforeQ(DLIST &l, DNODE *Tam, DNODE *q) {
DNODE *p;
p = q->pPrev;
if (q != NULL) {
Tam->pNext = q;
q->pPrev = Tam;
Tam->pPrev = p;
if (p != NULL)
p->pNext = Tam;
if (q == l.pHead)
l.pHead = Tam;
Trang 99
} else
AddDEnd(l, Tam);
}
6 Hủy một phần tử trong danh sách
• Hủy phần tử ĐẦU danh sách
P
P
P
• Thuật toán
Nếu (pHead!=NULL) thì //danh sach có hơn một phần tử +p=pHead
+ pHead = pHead ->pNext + pHead =pPrev=NULL +delete p
• Hàm hủy phần tử đầu trong danh sách
Trang 1010
void DeleteDFirst(DLIST &l) {
DNODE *p;
if (l.pHead != NULL) {
p = l.pHead;
l.pHead = l.pHead->pNext;
l.pHead->pPrev = NULL;
delete p;
if (l.pHead == NULL)
l.pTail = NULL;
} }
• Hủy phần tử CUỐI trong danh sách
P
P
P q
• Thuật toán Nếu (pHead!=NULL) thì //danh sach có hơn một phần
tử +p=pTail +pTail=pTail->pPrev +pTail=pNext=NULL +delete p
• Hàm hủy phần tử cuối trong danh sách
Trang 1111
void DeleteDEnd(DLIST &l) {
DNODE *p;
if (l.pHead != NULL) //tuc xau co hon mot phan tu
{
p = l.pTail;
l.pTail = l.pTail->pPrev;
l.pTail->pNext = NULL;
delete p;
if (l.pTail == NULL)
l.pHead = NULL;
} }
• Hủy phần tử SAU phần tử q trong danh sách
pHead
q
pTail
p
p
p
pTail
pTail
• Thuật toán Nếu (q!=NULL) thì +q=q->pNext
Trang 1212
+ Nếu (q!=NULL) thì q->pNext =p->pNext Nếu là nút CUỐI danh sách thì Tail=q
Ngược lại p->pNext->pPrev=q delete p
• Hàm hủy phần tử sau phần tử q trong danh sách
void DeleteDLastQ(DLIST &l, DNODE *q) {
DNODE *p;//luu node dung sau node q
if (q != NULL) {
delete p;
} }
else
DeleteDFirst(l);
}
• Hủy phần tử TRƯỚC phần tử q trong danh sách
Trang 1313
pHead
q
pHead
q
p
pTail
q
p
pTail pHead
• Thuật toán Nếu (q!=NULL) thì //nếu tồn tại q +q=q->pPrev
+ Nếu (q!=NULL) thì q->pPrev=p->pPrev Nếu là nút đầu danh sách thì Head=q
Ngược lại (p->pPrev)->pNext=q delete p
• Hàm hủy phần tử TRƯỚC phần tử q trong danh sách
void DeleteDBeforeQ(DLIST &l, DNODE *q) {
DNODE *p;
if (q != NULL) //tuc ton tai node q {
Trang 1414
danh sách
} else
}
• Hủy phần tử có khóa là x trong danh sách Thao tác thực hiện:
Bước 1: Duyệt danh sách và tìm phần tử có thành phần Info bằng x
Bước 2:
Nếu có tìm thấy phần tử khóa bằng x thì +Nếu x ở đầu danh sách thì gọi hàm hủy phần tử đầu danh sách
+Ngược lại nếu x ở cuối danh sách thì gọi hàm hủy phần tử cuối danh sách
+ Ngược lại gọi hàm hủy phần tử sau q hoặc trước q
• Hàm hủy phần tử có khóa là x trong danh sách
int DeleteX(DLIST &l, int x) {
DNODE *p;
DNODE *q;
q = NULL;
p = l.pHead;
while (p != NULL) {
if (p->Info == x)
break;
q = p;//q la Node co truong Info = x
p = p->pNext;
}
Trang 1515
if (q == NULL)
return 0;//khong tim thay Node nao co truong Info =x
if (q != NULL)
DeleteDLastQ(l, q);
else
DeleteDFirst(l);
return 1;
}