You are on page 1of 26

IV.

Danh sách liên kết kép

1.Khai báo CTDL:


lMỗi Node gồm:
– Data: là một cấu trúc để mô tả thông tin được lưu trữ
trong nút
– Linked: gồm hai con trỏ để chỉ liên kết với phần tử
trước và phần tử sau trong danh sách.

92 Danh sách liên kết


l Định nghĩa một nút trong danh sách
struct DNode
{
Data infor;
struct DNode *next;
struct DNode *previous;
};
l Định nghĩa danh sách
struct DLIST
{
DNode *Head;
DNode *Tail;
};
DLIST DQ;
93 Danh sách liên kết
* Ví dụ:
struct SV struct DLIST
{ {
int MSV; DNode *Head;
char hoten[25]; DNode *Tail;
float dtb; } ;
} ;
struct DNode DList DQ;
{
SV info;
struct DNode *next;
struct DNode *previous;
} ;

MSV MSV MSV

*previuos
*previuos

*previuos

hoten *next hoten *next hoten *next

dtb dtb dtb


94 Danh sách liên kết
2. Các thao các trên danh sách kép

üTạo danh sách


üChèn
üXóa
üTìm kiếm
üSắp xếp
üHiển thị
ü…

95 Danh sách liên kết


Bài tập áp dụng

lCho thông tin của Sinh Viên gồm: mã sinh viên, họ tên, điểm TB
lThực hiện lưu danh sách Sinh Viên bằng DSLK kép
lThực hiện các yêu cầu sau
–Nhập danh sách Sinh viên
–In lại toàn bộ danh sách Sinh Viên
–In sinh viên có ĐTB < 7
–Tìm kiếm sinh viên theo tên sinh viên
–SX DSSV giảm dần theo ĐTB
lViết chương trình thực hiện các chức năng trên

96 Danh sách liên kết


a. Tạo danh sách

lGồm:
–Khởi tạo danh sách rỗng ó Init
–Tạo nút chứa thông tin cần lưu trữ ó getNode

97 Danh sách liên kết


* Khởi tạo danh sách kép rỗng:

void Init( DLIST &DQ )


{
DQ.Head = NULL;
DQ.Tail = NULL;
}

98 Danh sách liên kết


* Thủ tục tạo một nút mới

DNode *Get_Node( Data x )


{
DNode *p;
p = new DNode();
if (p == NULL)
{
printf(”Khong du bo nho”);
exit(1);
}
p -> infor = x;
p -> next = NULL;
p -> previous = NULL;
return p;
}

99 Danh sách liên kết


Chèn thêm phần tử vào danh sách:

l Các trường hợp:


– Chèn mới vào đầu danh sách
– Chèn mới vào cuối danh sách
– Chèn mới vào sau một phần tử q đã biết
– Chèn mới vào trước một phần tử q đã biết

100 Danh sách liên kết


* Chèn thêm vào đầu danh sách:

void AddFirst( DLIST &DQ, DNode *new_element )


{
if ( DQ.Head == NULL ) //danh sách rỗng
{
DQ.Head = new_element;
DQ.Tail = DQ.Head;
}
else //danh sách không rỗng
{
new_element -> next = DQ.Head;
DQ.Head -> previous = new_element;
DQ.Head = new_element;
}
}
102 Danh sách liên kết
* Chèn thêm vào cuối danh sách:

void AddLast( DLIST &DQ, DNode *new_element )


{
if ( DQ.Head == NULL )
{
DQ.Head = new_element;
DQ.Tail = DQ.Head;
}
else //danh sách không rỗng
{
DQ.Tail -> next = new_element;
new_element -> previous = DQ.Tail;
DQ.Tail = new_element;
}
}
103 Danh sách liên kết
* Chèn thêm vào sau phần tử q:

void AddAfter( DLIST &DQ, DNode *q,


DNode *new_element )
{
DNode *p = q -> next;
if (q != NULL)
{
new_element->next = p;
new_element->previous = q;
q->next = new_element;
if (p != NULL)
p->previous = new_element;
if (q == DQ.Tail)
DQ.Tail = new_element;
}
104 } Danh sách liên kết
* Chèn thêm vào trước phần tử q:

void AddBefore( DLIST &DQ, DNode *q,


DNode *new_element)
{
DNode *p = q -> previous;
if ( q != NULL )
{
new_element -> next = q;
new_element -> previous = p;
q -> previous = new_element;
if (p != NULL) p -> next = new_element;
if (q == DQ.Head)
DQ.Head = new_element;
}
105 } Danh sách liên kết
Hủy một phần tử khỏi danh sách

ü Có các trường hợp:


• Hủy phần tử đầu
• Hủy phần tử cuối
• Hủy phần tử đứng sau phần tử q
• Hủy phần tử đứng trước phần tử q
• Hủy một phần tử có khóa là k

106 Danh sách liên kết


DQ.Head DQ.Tail
A B C D

DQ.Head DQ.Tail
A B C D

q p
DQ.Head DQ.Tail
A B C D

107 Danh sách liên kết


* Hủy một phần tử đầu danh sách:
DQ.Head DQ.Tail

A B C D

void RemoveHead( DLIST &DQ )


{
DNode *p;
if ( DQ.Head != NULL)
{
p = DQ.Head;
DQ.Head = DQ.Head -> next;
DQ.Head -> prev = NULL;
free(p);
if ( DQ.Head == NULL)
DQ.Tail = NULL;
}
}
108 Danh sách liên kết
* Hủy một phần tử cuối danh sách:
DQ.Head DQ.Tail

A B C D

void RemoveTail ( DLIST &DQ )


{
DNode *p;
if ( DQ.Tail != NULL)
{
p = DQ.Tail;
DQ.Tail = DQ.Tail -> prev;
DQ.Tail -> next = NULL;
free(p);
if ( DQ.Head == NULL) DQ.Tail = NULL;
else DQ.Head ->prev = NULL;
}
}
109 Danh sách liên kết
* Hủy một phần tử đứng sau phần tử q:

q p
DQ.Head DQ.Tail

A B C D

110 Danh sách liên kết


Cài đặt hủy phần tử đứng sau phần tử q:
void RemoveAfter ( DLIST &DQ, DNode *q )
{
DNode *p;
if ( q = = NULL ) MoveFirst(DQ);
else //phan tu q co ton tai trong danh sach
{
if ( q == DQ.Tail )
{
printf ( "Ko xoa duoc vi ko co phan tu sau q" ) ;
exit ( 1 );
}
else
{
p = q->next; //p la phan se bi xoa
q -> next = p -> next;
if ( p = = DQ.Tail ) DQ.Tail = q;
else p -> next -> previous = q;
free(p);
}
}
}
111 Danh sách liên kết
* Hủy một phần tử đứng trước phần tử q:
p q
DQ.Head DQ.Tail

A B C D

void RemoveBefore ( DLIST &DQ, Dnode *q )


{
DNode *p;
if ( q == NULL ) MoveLast(DQ);
else //Co phan tu q
{
if (q == DQ.Head)
{
printf("\n Ko xoa duoc do dang o vi tri dau");
exit(1);
}
p = q -> previous; //lay phan tu can huy bo
q -> previous = p -> previous;
if ( p == DQ.Head ) DQ.Head = q;
else p -> previous -> nex t = q;
free(p);
}
112 } Danh sách liên kết
* Hủy một phần tử có khóa k:

l Bước 1: Tìm phần tử có khóa là k


l Bước 2: Xóa phần tử vừa tìm được

113 Danh sách liên kết


Cài đặt xóa phần tử có khóa k:

void MoveKey ( DLIST &DQ, Data k)


{
DNode *p;
p = Search (DQ,k); //Tìm kiếm phần tử để xóa
if ( p = = NULL )
{
printf("\n Khong co phan tu co trong danh sach", k);
exit(1);
}
else
{
if ( ( p = = DQ.Head ) && ( p = = DQ.Tail) )
{ DQ.Head = NULL; DQ.Tail = NULL; }
else if ( p = = DQ.Head ) DQ.Head = p->next;
else if ( p = = DQ.Tail )
{ p -> previous -> next = NULL; DQ.Tail = p -> previous; }
else
{
p -> previous -> next = p -> next;
p -> next -> previous = p -> previous;
}
free(p);
}
}

114 Danh sách liên kết


*Tìm kiếm phần tử có khóa xác định:

l danh sách kép có thể kết nối với phần tử trước và


sau nên, thực hiện tìm kiếm bằng cách:
– Xuất phát từ đầu danh sách
– Xuất phát từ cuối danh sách.

115 Danh sách liên kết


* Cài đặt tìm kiếm từ đầu danh sách:
DNode *DSearch( DLIST DQ, Data k )
{
DNode *p;
for ( p = DQ.Head; p != NULL; p = p -> next )
if ( p -> info = = k ) break;
return p;
}

DNode *DSearch( DLIST DQ, Data k )


{
DNode *p;
for ( p = DQ.Tail; p != NULL; p = p -> previous )
if ( p -> info = = k ) break;
return p;
} 116
116 Danh sách liên kết
e. Sắp xếp các phần tử của danh sách:

l thựchiện sắp xếp bằng cách:


– Xuất phát từ đầu danh sách
– Xuất phát từ cuối danh sách.

117
117 Danh sách liên kết
* Cài đặt Sắp xếp bằng cách duyệt từ cuối:

void SX_DuyetCuoi( DLIST DQ )


{
DNode *p, *q;
for ( p = DQ.Tail; p != NULL; p = p -> previous )
for ( q = p -> previous; q != NULL; q = q -> previous )
if ( p -> info > q -> info )
HoanDoi( p -> info, q -> info );
}

118
118 Danh sách liên kết

You might also like