Tải bản đầy đủ (.docx) (13 trang)

Danh sách liên kết lép Tiểu luận cấu trúc dữ liệu

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (360.81 KB, 13 trang )

TRƯỜNG ĐẠI HỌC AN GIANG
KHOA CÔNG NGHỆ THÔNG TIN

BÁO CÁO
DANH SÁCH LIÊN KẾT KÉP

NGUYỄN MINH ĐỨC – DH22PM
AN GIANG, 05 – 2022

1


LỜI NĨI ĐẦU
*****

Ngày nay, nghành cơng nghệ thơng tin đang phát triển mạnh mẽ và được ứng dụng phổ
biến khắp các mọi mặt đời sống. Từ vật chất tới các mạng xã hội, thế giới hiện nay ngày càng phát
triển là do nghành công nghệ thông tin đạt được nhiều thành tựu và phát triển Chính vì tầm quan
trọng và đa dạng về nghành cơng nghệ thơng tin mà địi hỏi các sinh viên công nghệ thông tin cần
phải nắm vững các nguyên lý và ứng dụng của các môn học từ khi cịn trên ghế nhà trường mà
hơm nay chúng ta sẽ nói về mơn “Cấu trúc dữ liệu và giải thuật”. Trong phạm vi mơn học, nhằm tìm
hiểu về danh sách liên kết, tác giả xin trình bày đề tài: Nghiên cứu và cài đặt danh sách liên kết kép

MỤC LỤC
CHƯƠNG 1: GIỚI THIỆU ĐỀ TÀI..............................................................2
CHƯƠNG 2: NỘI DUNG ĐỀ TÀI...............................................................3
CHƯƠNG 3: CHƯƠNG TRÌNH.................................................................5
CHƯƠNG 4: ĐÁNH GIÁ KẾT QUẢ NGHIÊN CỨU VÀ KẾT LUẬN...............13
TÀI LIỆU THAM KHẢO...........................................................................13

Nguyễn Minh Đức – DH22PM


CHƯƠNG I: GIỚI THIỆU ĐỀ TÀI
2


I. Phát biểu đề tài.
Trước khi tìm hiểu và nghiên cứu danh sách liên kết đôi, trước hết chúng ta phải hiểu khái
niệm danh sách liên kết đơn (Linked List): Giống như kiểu dữ liệu Array (mảng), Linked List là một
cấu trúc dữ liệu tuyến tính. Tuy nhiên khác với array, các phần tử của linked list không được lưu trữ
tại các vị trí ơ nhớ liền kề nhau, mà các phần tử của linked list sẽ được liên kết với nhau bằng cách
sử dụng các con trỏ.
So với Linked List thì một Doubly Linked List (DLL – danh sách liên kết kép) sẽ chứa thêm
một con trỏ phụ, thường được gọi là previous pointer (con trỏ trỏ đến node trước đó), con trỏ
previous này cùng với con trỏ next và phần data chứa dữ liệu/giá trị của node (2 thành phần này
đều nằm trong một node của Linked List thông thường) sẽ là những thành phần tạo nên một
Doubly Linked List, và trong báo cáo này, chúng ta sẽ nghiên cứu và cài đặt danh sách liên kết kép.

II. Phạm vi, đối tượng nghiên cứu.
Danh sách liên kết kép (Doubly linked list).

III. Mục tiêu.
- Tìm hiểu về cấu trúc, thuật tốn chương trình được sử dụng khi cài đặt dánh sách liên kết
kép.
- Viết giải thuật.

IV. Nguồn và phương pháp nghiên cứu.
- Nguồn nghiên cứu: từ giáo trình “Cấu trúc dữ liệu và giải thuật, tài liệu từ các web.
- Phương pháp: tìm hiểu tài liệu, từ đó viết các chương trình, chạy thử và kiểm tra độ chính
xác của chương trình.

3



CHƯƠNG II: NỘI DUNG ĐỀ TÀI
I. Danh sách liên kết.
Danh sách liên kết là danh sách mà các phần tử được liên kết với nhau nhờ vào vùng liên
kết của chúng, mỗi phần tử của danh sách được lưu trữ trong một phần tử nhớ gồm một số đơn vị
bộ nhớ kế tiếp nhau được gọi là nút.
Mỗi nút có 2 thành phần:
+ Trường dữ liệu: lưu trữ thông tin dữ liệu của nút.
+ Trường con trỏ: chứa địa chỉ của nút kế tiếp hay trước nó.

II. Danh sách liên kết kép (Doubly Linked List).
1. Khái niệm.
- Danh sách liên kết kép là danh sách mà mỗi phần tử trong danh sách có kết nối với
một phần tử đứng trước và một phần tử đứng sau nó.
- Danh sách liên kết kép được xác định bởi hai con trỏ:
+ Left: trỏ vào node đầu tiên.
+ Right: trỏ vào node cuối cùng.
2. Khai báo.
- Danh sách nối kép gồm các nút được nối với nhau theo 2 chiều. Mỗi nút là một
bản ghi gồm ba trường:
+ Trường thứ nhất chứa giá trị lưu trong nút đó.
+ Trường thứ hai (Next) chứa liên kết (Con trỏ) tới nút kế tiếp, tức là chứa một
thông tin đủ để biết nút kế tiếp nút đó là nút nào, trong trường hợp là nút cuối cùng,
trường liên kết này gán một giá trị đặc biệt.
+ Trường thứ ba (Prev) chứa liên kết (Con trỏ) tới nút liền trước, tức là chứa một
thông tin đủ để biết nút đứng trước nút đó trong danh sách là nút nào, trong trường hợp là
nút đầu tiên trường này được gán một giá trị đặc biệt.
- Khác với danh sách nối đơn, danh sách nối kép có hai chốt:
+ Nút chốt đầu tiên trong danh sách được gọi là First.

+ Nút cuối cùng trong danh sách được gọi là Last.
- Để duyệt danh sách nối kép, ta có hai cách:
+ Hoặc bắt đầu từ First, dựa vào liên kết Next để sang nút kế tiếp, đến khi gặp giá
trị đặc biệt (Nút cuối) thì dừng lại.

4


+ Hoặc bắt đầu từ Last, dựa vào liên kết Prev để đi sang nút liền trước. Việc
chèn/xóa vào danh sách nối kép cũng đơn giản chỉ là kỹ thuật chỉnh lại các mối liên kết giữa
các nút cho hợp lý.
- Tổ chứa danh sách liên kết kép: Trong mỗi nút ngồi phần Data cịn có hai con trỏ,
một trỏ đến nút đứng trước nó và một trỏ đến nút đứng sau.
Liên kết sau
Data

Giá trị

Liên kết trước

Hình ảnh minh họa
- Như vậy cấu trúc mỗi nút sẽ được biểu diễn như sau:
Lptr

Data

Rptr

- Trong đó:
+ Data chứa dữ liệu của nút.

+ Lptr: con trỏ trái, trỏ tới nút đứng trước.
+ Rptr: con trỏ phải, trỏ
tới nút đứng sau.
(Lptr của nút cực trái và Rptr của nút cực phải là Null)

CHƯƠNG III: CHƯƠNG TRÌNH
5


1. Cài đặt một node DLL (Doubly linked list) bằng ngôn ngữ C:

2. Chèn thêm node mới vào đầu DLL (5 Bước) bằng ngôn ngữ C:
Node mới sẽ luôn luôn được chèn vào phía trước node head của linked list được cho. Và
node vừa mới được chèn thêm vào sẽ trở thành node head mới của DLL. Ví dụ, nếu DLL được cho
có dạng 10 -> 15 -> 20 -> 25 và chúng ta chèn thêm một phần tử 5 vào phía trước, lúc đó DLL này
sẽ trở thành 5 -> 10 -> 15 -> 20 -> 25. Chúng ta hãy gọi hàm có chức năng chèn thêm node mới vào
phần đầu của DLL là hàm push(). Hàm push() phải nhận vào một con trỏ trỏ đến con trỏ head, bởi
vì hàm push phải thay đổi con trỏ head để con trỏ head trỏ đến node mới được chèn vào. Truyền
vào cho hàm push() một tham chiếu (con trỏ trỏ đến con trỏ) tới node head của DLL, một giá trị int
mà node đó sẽ chứa, hàm push() sẽ thực hiện chèn thêm một node mới vào phần đầu của danh
sách liên kết kép (DLL):

1. Cấp phát bộ nhớ cho node mới
2. Truyền dữ liệu (chính là giá trị int) vào node mới
3. Làm cho con trỏ next của node mới trỏ đến (bằng với) con trỏ head của DLL, và làm cho con trỏ
previous của node mới bằng với NULL
4. Làm cho con trỏ prev của node head trỏ đến node mới cần được chèn vào
5. Làm cho con trỏ head trỏ đến node mới được chèn vào

6



3. Chèn thêm một node mới vào sau một node cụ thể trong DLL (7 bước) bằng
ngôn ngữ C:
Ở đây, chúng ta được cho một con trỏ trỏ đến một node, là con trỏ prev_node, và node mới sẽ
được chèn vào phía sau một node cụ thể trong DLL.

Dưới đây là 7 bước để chèn thêm một node mới vào phía sau một node cụ thể trong DLL:
Hàm insertAfter() sẽ nhận vào một node để làm prev_node, và một giá trị int mà node đó sẽ
chứa. Hàm insertAfter() sẽ thực hiện chèn thêm một node mới vào phía sau node được cho.
1. Kiểm tra xem prev_node nhận vào có NULL hay khơng, nếu NULL thì return ln.
2. Cấp phát bộ nhớ cho node mới.

7


3. Truyền dữ liệu (giá trị) vào node mới
4. Làm cho con trỏ next của node mới trỏ đến (bằng với) con trỏ next của prev_node
5. Làm cho con trỏ next của prev_node trỏ đến (bằng với) node mới được chèn vào
6. Làm cho con trỏ prev của node mới được chèn vào trỏ đến (bằng với node prev_node. Hay nói cách
khác là làm cho prev_node trở thành node trước đó của new_node
7. Làm cho con trỏ prev của con trỏ next của new_node trỏ đến (bằng với) chính new_node

4. Chèn thêm một node mới vào cuối DLL (7 bước) bằng ngôn ngữ C:

8


Trong trường hợp này, node mới sẽ luôn luôn được chèn thêm vào phía sau node cuối cùng
của DLL được cho. Ví dụ, nếu DLL được cho có dạng 5 -> 10 -> 15 -> 20 -> 25 và chúng ta chèn

thêm một phần tử 30 vào cuối, lúc này DLL sẽ trở thành 5 -> 10 -> 15 -> 20 -> 25 -> 30.
Bởi vì về cơ bản, danh sách liên kết kép hay danh sách liên kết nói chung đều được đại diện
bởi con trỏ head của chúng, vậy nên chúng ta sẽ phải duyệt từ đầu tới cuối danh sách và sau đó
thay đổi con trỏ next của node cuối cùng để cho con trỏ next này trỏ đến node mới được chèn
thêm vào.

Dưới dây là 7 bước để chèn thêm một node mới vào cuối danh sách liên kết kép.
Hàm append() sẽ nhận vào một tham chiếu (con trỏ trỏ đến con trỏ) tới con trỏ head của
một DLL và một giá trị int mà node đó sẽ chứa. Hàm append() sẽ thực hiện chèn thêm một node
mới vào phần cuối của DLL.
1. Cấp phát bộ nhớ cho new_node
2. Truyền dữ liệu (giá trị) vào new_node
3. new_node sẽ trở thành node cuối cùng của DLL, vì vậy chúng ta phải làm cho con trỏ next của
new_node trở thành/bằng với NULL
4. Nếu DLL đang trống, vậy thì ta sẽ làm cho new_node trở thành node head của DLL luôn, tức là
làm cho con trỏ head của DLL trỏ đến new_node
5. Nếu DLL không trống, ta sẽ duyệt tới node cuối cùng của DLL
6. Thay đổi con trỏ next của node cuối cùng của DLL để cho con trỏ next này trỏ đến new_node

9


7. Làm cho node từng là cuối cùng của DLL trở thành node trước đó của new_node, tức là làm cho
con trỏ prev của new_node trỏ đến/bằng với node từng là cuối cùng của DLL.

5. Ghép 2 danh sách nối kép bằng ngôn ngữ C:
#include<conio.h>
#include<stdio.h>
#include<ctype.h>
typedef int item;

typedef struct Node
{
item Data;
Node *Left;
Node *Right;
};
typedef struct DList
{

10


Node *Head;
Node *Tail;
};
Node *GetNode(int x)
{
Node *P;
P=new(Node);
if(P==NULL)
{
printf("\n Khong du bo nho");
return NULL;
}
P->Data=x;
P->Left = P->Right =NULL;
return P;
}
void Init(DList &L)
{

L.Head = NULL;
L.Tail = NULL;
}
void Addtail(DList &L, Node *new_e)
{
if(L.Head==NULL)
{
L.Head=L.Tail=new_e;
}
else
{
L.Tail->Right=new_e;
L.Tail=new_e;
}
}
void nhap(DList &L)
{
int i,n,x;
11


Node *P;
printf("\n Nhap so luong phan tu danh sach 1: ");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
printf("\n A[%d]= ",i);
scanf("%d",&x);
P=GetNode(x);
Addtail(L,P);

}
printf("\n Nhap so luong phan tu danh sach 2: ");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
printf("\n B[%d]= ",i);
scanf("%d",&x);
P=GetNode(x);
Addtail(L,P);
}
}
void xuat(DList &L)
{
printf("\n Danh sach sau khi ghep la: \n");
Node *P;
P = L.Head;
while(P!=NULL)
{
printf("%d
",P->Data);
P=P->Right;
}
}
int main()
{
DList L;
Node *P;
Init(L);
nhap(L);
xuat(L);


12


getch();
}

CHƯƠNG IV: ĐÁNH GIÁ KẾT QUẢ NGHIÊN CỨU VÀ KẾT LUẬN
- Ưu điểm: xâu kép có mối liên kết hai chiều nên từ một phần tử bất kỳ có thể truy xuất một phần
tử bất kỳ khác. Thao tác xóa node trong DLL sẽ hiệu quả hơn vì chúng ta có được con trỏ trỏ đến
node cần xóa.
- Nhược điểm: xâu kép tốn chi phí gấp đơi so với xâu đơn cho việc lưu trữ các mối liên kết. Ðiều
này khiến việc cập nhật cũng nặng nề hơn trong một số trường hợp. Như vậy ta cần cân nhắc lựa
chọn CTDL hợp lý khi cài đặt cho một ứng dụng cụ thể.

TÀI LIỆU THAM KHẢO
Giáo trình Cấu trúc dữ liệu và giải thuật - Nxb Thống kê - Đại học kinh tế quốc dân.

/>
13



×