Danh sách liên kết đôi (Doubly Linked List)

Download Report

Transcript Danh sách liên kết đôi (Doubly Linked List)

Danh sách liên kết đôi
(Doubly Linked List)
• Là danh sách mà mỗi phần tử có 2 mối liên
kết:
– Next: để kết nối với phần tử kế tiếp
– Prev: để kết nối với phần tử trước nó
head
pos
rear
Cài đặt DSLK đôi
• Cài đặt: dựa trên con trỏ, bao gồm:
• 3 con trỏ: head (đầu ds), pos (phần tử hiện hành), và
rear (cuối ds)
• biến count: số phần tử của danh sách
typedef struct nodet {
elem data;
struct nodet *next, *prev;
} node;
typedef node *nodeptr;
next
data
prev
head
pos
rear
typedef struct {
nodeptr head, pos, rear;
int count;
} list;
Các thao tác trên danh sách liên kết đôi
• Tương tự như danh sách liên kết đơn ngoại trừ
2 thao tác (cục bộ) làm thay đổi liên kết:
– Chèn phần tử vào danh sách
– Xóa phần tử trong danh sách liên kết
• Bổ sung thêm một số thao tác như:
– Khởi đầu từ cuối danh sách
– Di chuyển qua phần tử trước phần tử hiện hành
Chèn phần tử x vào danh sách
p
q
head
rear
ewp
• Chèn đầu danh sách (xét theo chiều xuôi):
– q = head
– newp->next = q
– head = newp
Chèn phần tử x vào danh sách
p
head
q
rear
newp
• Chèn sau p (xét theo chiều xuôi):
– q = p->next
– newp->next=q
– p->next = newp
Giải thuật chèn
1.
2.
3.
Cấp phát bộ nhớ cho newp, gán dữ liệu
Xác định con trỏ q=(p==NULL? head:p->next)
Kết nối xuôi
3.1 newpnext = q;
3.2 Nếu p=NULL thì
head = newp
3.3 Ngược lại
pnext = newp
4.
Kết nối ngược
4.1 newpprev = p;
4.2 Nếu q=NULL thì
rear = newp
4.3 Ngược lại
qprev = newp
5.
Tăng biến count
Hàm chèn phần tử vào danh sách
void insertlist(list &l, elem &x, nodeptr p)
{
nodeptr newp, q;
newp = new node;
memcpy(&newp->data, &x, sizeof(elem));
q = (p==NULL? l.head: p->next);
newp->next = q;
if (p==NULL)
l.head = newp;
else
p->next = newp;
newp->prev = p;
if (q==NULL)
l.rear = newp;
else
q->prev = newp;
l.count++;
Hàm xóa phần tử trongdanh sách
void deletelist(list &l, nodeptr p)
{
nodeptr t, q;
t = (p==NULL? l.head: p->next);
q = t->next;
if (p==NULL)
l.head = q;
else
p->next = q;
if (q==NULL)
l.rear = p;
else
q->prev = p;
delete t;
l.count--;
}
Bổ sung 2 hàm
• Khởi đầu tử cuối danh sách
void startend(list &l)
{
l.pos = l.rear;
}
• Di chuyển đến phần tử trước phần tử hiện hành
void skipbefore(list &l)
{
if (l.pos == NULL)
l.pos = l.rear;
else
l.pos = l.pos->prev;
}
• Thiết kế kiểu số nguyên lớn với các phép
toán: cộng, nhân. Áp dụng tính 100!, 7100
• 349093429
• 675432