1. Trang chủ
  2. » Công Nghệ Thông Tin

Bài giảng Cấu trúc dữ liệu: Chương 4 - Trịnh Xuân

8 20 0

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 8
Dung lượng 1,19 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Chương 4 cung cấp kiến thức về danh sách liên kết. Chương này gồm có những nội dung chính sau: Định nghĩa danh sách liên kết, danh sách liên kết đơn, danh sách liên kết kép. Mời các bạn cùng tham khảo để nắm bắt các nội dung chi tiết.

Trang 1

CHƯƠNG IV:

DANH SÁCH

LIÊN KẾT

Danh sách liên kết

14

I Định nghĩa

!  Danh sách liên kết là tập hợp các phần tử được liên kết móc nối liên tiếp với nhau, có kiểu truy cập tuần tự Mỗi một phần tử là một nút (Node)

!  Số phần tử là biến động

!  Nút gồm hai phần:

–   Data - Dữ liệu : là các thành phần dữ liệu mà một nút đó lưu trữ

–   Linked - Liên kết : là con trỏ kiểu nút đang định nghĩa được dùng để liên kết với các nút khác

!  Ví dụ:

Danh sách liên kết

22

  Danh sách liên kết đơn : mỗi một phần tử của

danh sách liên kết duy nhất với một phần tử đứng

sau nó

  Danh sách liên kết kép : mỗi một phần tử của

danh sách liên kết với cả phần tử đứng trước và

đứng sau trong danh sách

*Phân loại danh sách liên kết

  Danh sách liên kết vòng : là danh sách mà phần

tử cuối liên kết với phần tử đầu của danh sách

Có hai loại danh sách liên kết vòng: vòng đơn và vòng kép

Danh sách liên kết

23

II Danh sách liên kết đơn

1  Khai báo CTDL

!  Khai báo CTDL DSLK Đơn:

–  Định nghĩa cấu trúc một nút

–  Định nghĩa cấu trúc danh sách

!  Cấu trúc mỗi nút gồm:

–  Info: kiểu cấu trúc

–  Next: kiểu con trỏ

!  Cấu trúc danh sách LK đơn gồm:

–  Head

–  Tail

Info Next

(Dữ liệu) (liên kết)

Danh sách liên kết

24

!  Cú pháp định nghĩa một nút:

struct < Node >

{ Data info ; //Khai báo dữ liệu - struct

struct Node * next ; //khai báo liên kết

} ;

!  Trong đó:

–  Data: là kiểu dữ liệu đã được khai báo để mô tả thành

phần dữ liệu chứa trong nút, là kiểu được định nghĩa sẵn

Danh sách liên kết

25

!  Cú pháp định nghĩa danh sách:

struct LIST

{

Node Head; // Phần tử dầu danh sách

Node Tail;//Phần tử cuối danh sách

} ; LIST Q; //tạo danh sách có tên là Q

Danh sách liên kết

26

Ví dụ

! Cho thông tin của Sinh viên gồm: mã sinh

viên, Họ tên, Điểm trung bình

! Khai báo CTDL dạng danh sách liên kết

đơn để lưu được danh sách SV trên

MSV hoten dtb

next

MSV hoten dtb

next

struct SV

{

int MSV;

char hoten[25];

float dtb;

} ;

struct Node

{

SV info;

struct Node *next;

};

struct LIST

{ Node Head ; Node Tail ; };

2 Các thao các trên danh sách đơn

! Các thao tác cơ bản sau:

–  Tạo danh sách

–  Duyệt danh sách

–  Chèn phần tử

–  Hủy phần tử

–  Tìm kiếm phần tử

–  Sắp xếp danh sách

–  

Trang 2

a Tạo danh sách:

! Để tạo danh sách, gồm các bước:

–  Khởi tạo danh sách rỗng

–  Tạo nút mới chứa thông tin nào đó

void init ( List &Q )

{

Q.Head = NULL;

Q.Tail = NULL;

}

Danh sách liên kết

30

Node* get_node( Data x )

{ Node *p;

p = new Node;

if ( p == NULL ) {

printf(“Ko du bo nho”);

exit(1);

}

p -> info = x;

p -> next = NULL;

return p;

}

=> Tạo phần tử mới: new_element = get_node(x);

Danh sách liên kết

31

b Chèn một phần tử mới vào danh sách:

! Các trường hợp sau –  Chèn vào đầu danh sách

–  Chèn vào cuối danh sách

–  Chèn vào sau một phần tử q đã biết

Danh sách liên kết

32

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

new_element

Thuật toán

Nếu danh sách rỗng

Phần tử đầu là phần tử mới chèn vào

Phần tử cuối cũng là phần tử đầu

Ngược lại (danh sách khác rỗng)

Phần tử mới trỏ tới phần tử đầu

Phần tử đầu là phần tử mới được chèn vào

Danh sách liên kết

33

3 3f 4 4f 8 …

10 9f

P P->Next = Q.Head

2f

Q.Head = P

Danh sách liên kết

34

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

new_element

Thuật toán Nếu danh sách rỗng:

Phần tử đầu là phần tử mới chèn vào Phần tử cuối là phần tử đầu

Ngược lại (danh sách khác rỗng):

Phần tử cuối là phần tử mới được chèn vào

Danh sách liên kết

35

5

4 4f 8 5f

Q.Tai

l

6 N

9f

P

N 9f

Q.Tail->Next

Q.Tail=P

Chèn thêm phần tử mới sau phần tử q đã biết

Thuật toán Nếu không có phần tử q " không chèn được Nếu có tồn tại phần tử q

-Phần tử mới móc tới phần tử sau phần tử q -Phần tử q móc tới phần tử mới

-Nếu phần tử q là phần tử cuối thì phần tử mới chèn là phần tử cuối mới

5

4 4f 8

7

P

9f

q 5f

5f N

P->Next = q->Next q->Next = P

Trang 3

B Tìm kiếm phần tử k trong danh sách

#   Ý tưởng: Danh sách đơn chỉ cho truy xuất tuần

tự tới từng phần tử " Á p dụng thuật toán tìm

tuyến tính để xác định có phần tử k trong danh

sách hay ko?

#  Để duyệt dùng một con trỏ p để duyệt qua các

nút của danh sách

56

X = 8

địa chỉ của nút tìm thấy là 4f

8

Danh sách liên kết

39

*Thuật toán

!  Bước 1: p = Q.Head; //p trỏ từ đầu danh

sách

!  Bước 2: kiểm tra danh sách còn phần tử và chưa

tìm thấy phần tử thì chuyển sang phần tử tiếp theo

Lặp trong khi (p!=NULL) và (p->info !=k) thì

p = p -> next;

!  Bước 3:

–  Nếu p != NULL:

!  Tìm thấy

!  p trỏ đến phần tử cần tìm

–  Ngược lại: ko tìm thấy (trả lại NULL)

Danh sách liên kết

40

Cài đặt:

Node *Search( LIST Q, Data k )

{ Node *p;

p = Q.Head;

while ( p != NULL ) {

if ( p -> info ==k ) break;

p = p -> next;

} return p;

}

Danh sách liên kết

41

Cài đặt:

Node *Search( LIST Q, Data k )

{

Node *p;

p = Q.Head;

while (( p != NULL ) && (p -> info !=k ))

p = p -> next;

return p;

}

Danh sách liên kết

42

c Duyệt danh sách

! Là kỹ thuật để xét qua được hết các phần

tử của danh sách

! Thực hiện

– Khai báo một con trỏ p có kiểu Node – Cho con trỏ p duyệt từ đầu đến cuối để đi

qua từng phần tử của Danh sách

! Thuật toán

Danh sách liên kết

43

Cài đặt

void Duyet_DS ( LIST Q)

{ Node *p;

p = Q.Head;

while ( p != NULL ) {

<< thực hiện thao tác xử lý>>

p = p -> next;

} }

Danh sách liên kết

44

Ví dụ:

! Viết hàm in danh sách sinh viên ra màn

hình

! Viết hàm in họ tên của tsinh viên có điểm

trên 8

! Viết hàm cho biết Họ tên của Sv có ĐTB

cao nhất

d Hủy một phần tử khỏi danh sách

#  Các trường hợp

  Hủy phần tử đầu

  Hủy phần tử đứng sau phần tử q xác định

  Hủy phần tử có giá trị xác định k

#  Chú ý: khi tạo nút thì dùng hàm cấp phát bộ nhớ

=> Khi hủy thì phải dùng hàm để giải phóng bộ nhớ

Hủy một phần tử đầu danh sách:

Q.Tail Q.Head

Thuật toán:

Nếu danh sách rỗng (không có phần tử đầu) => không thực hiện xóa được

Nếu có phần tử đầu Lưu tạm thời phần tử đầu – lưu vào p

Chuyển phần tử đầu sang phần tử tiếp theo Xóa phần tử đầu đã được lưu tạm – xóa p

Kiểm tra: Nếu danh sách chỉ có một phần tử, khi xóa phần

tử đi thì phần tử cuối cùng không còn

Trang 4

Thuật toán:

2f

P

P = Q.Head

Q.Head = Q.Head->Next

Danh sách liên kết

48

Hủy một phần tử đứng sau phần tử q:

#   Thuật toán

#  Nếu có phần tử q

$  Lưu phần tử đứng sau phần tử q – lưu vào p

$  Nếu có phần tử p (q không phải là phần tử cuôi)

$  Tách phần tử p ra khỏi danh sách

$  Nối phần tử q với phần tử sau p

$  Giải phóng phần tử p

Danh sách liên kết

49

2f

3f 4f

p

p = q->Next

q->Next = p->Next

Q.Head

Danh sách liên kết

50

Hủy một phần tử có khóa k

!  Thuật toán:

!  Bước 1:

Tìm phần tử p có khóa k và phần tử q đứng trước

!  Bước 2:

Nếu (p!= NULL) thì // tìm thấy k

Hủy p ra khỏi xâu tương tự hủy phần tử sau q;

Ngược lại

Báo không có k;

Danh sách liên kết

51

* Cài đặt:

int RemoveNode( LIST &Q, Data k ) {

NODE *p = Q.Head, *q = NULL;

while( p != NULL) {

if (p->info == k) break;

q = p;

p = p->next;

}

if (p == NULL) return 0; //Không tìm thấy k

Danh sách liên kết

52

if (q != NULL) {

if(p == Q.Tail) Q.Tail = q;

q->next = p->next;

delete p;

} else //p là phần tử đầu xâu

{ Q.Head = p -> next;

if ( Q.Head == NULL) Q.Tail = NULL; }

return 1;

}

Danh sách liên kết

53

e Sắp xếp danh sách

! Để sắp xếp có hai phương án:

–  Hoán vị nội dung của phần tử

–  Thay đổi mối liên kết của phần tử

Hoán vị nội dung của phần tử:

#   Là thực hiện thay đổi trực tiếp thành phần infor trong mỗi nút còn thứ tự liên kết của các nút là

không thay đổi

4f

4

3f

N

6 5f

7

4f

4

3f

N

7

5f

6

Cài đặt sắp xếp danh sách bằng cách thay đổi nội dung:

void ListSortInterchange( LIST &Q )

{ Node *p, *q; //p và q la hai bien dieu khien Data tg;

for(p = Q.Head;p != NULL; p = p->next) for(q = p -> next;q!=NULL; q = q->next )

if ( p->info> q->info )

}

Trang 5

Ví dụ

! Viết hàm sắp xếp danh sách sinh viên theo

thứ tự ĐTB tăng dần

Danh sách liên kết

57

void ListSortInterchange( LIST &Q )

{ Node *p, *q; //p và q la hai bien dieu khien

Data tg;

p = Q.Head;

while ( p != NULL ) {

q = p -> next;

while( q != NULL ) {

if ( p->info.DTB > q->info.TDB )

{ tg = p->info; p->info = q->info; q->info = tg; }

q = q->next;

}

p = p->next;

} }

Danh sách liên kết

58

Thay đổi mối liên kết

! Là thực hiện thay đổi trực tiếp thành phần

các nút là thay đổi

! Ý tưởng: Tạo một danh sách mới là danh sách có thứ tự lần lượt lấy từ danh sách cũ (đồng thời huỷ danh sách cũ )

Danh sách liên kết

59

4f

4

3f

N

6 5f

7

6

Q.Head

Q.Tail 5f

3f

Q.Head

5f

4f Q.Tail

N

7 5f

Danh sách liên kết

60

! Thuật toán sắp xếp bằng thay đổi mối liên kết :

phần tử min là phần tử nhỏ nhất ;

Tail);

cũ Q (Head, Tail);

Danh sách liên kết

61

Bài tập thực hành

!  Cho thông tin của cán bộ gồm: mã cán bộ, họ tên, ngày sinh, hệ số lương, phụ cấp và thành tiền (= hệ số lượng *

1050000 + phụ cấp)

với các yêu cầu:

–  In lại ds cán bộ đã có

–  Tìm kiếm cán bộ có mã là k

! Áp dụng các yêu cầu trên

Danh sách liên kết

62

Bài tập thực hành (y/c chi tiết)

!  Khai Báo CTDL DSLK đơn chứa DS Cán bộ gồm: MCB, Hoten,

Tuoi, HSL, PC, TT(=HSL* 1.050.000 + PC)

!  Định nghĩa các CTC sau:

!  Áp dụng lần lượt các CTC trên dưới dạng menu lựa chọn:

–  0 Thoát

–  1 Tạo DSCB 2 In lại DSCB

–  3 Tìm kiếm CB theo mã nào đó 4 Đếm số CB lương từ 2 đến 3 triệu

–  5 Tính tổng lương của các cán bộ 6 …

Nhập một cán bộ In một cán bộ

Khởi tạo DSLK rỗng Tạo một nút chứa 1 cán bộ nào đó

Chèn thêm 1 cán bộ vào đầu DSLK đơn In DSCB

Tìm kiếm một CB có mã nào đó Tính tổng lương của các CB

Đếm số CB có lương từ 2 đến 3 triệu SX DSCB tăng dần theo tổng lương

Chèn thêm CB vào sau CB có mã là x

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

1  Khai báo CTDL:

–  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.

!   Định nghĩa một nút trong danh sách struct DNode

{

Data infor; //Khai báo các thành phần dữ liệu

struct DNode *next; khai báo liên kết sau struct DNode *previous; khai báo liên kết trước

};

!  Định nghĩa danh sách

struct DLIST

{

DNode *Head;

DNode *Tail;

};

DLIST DQ; //Tạo danh sách kép lấy tên là DQ

DNode *new_element;

Trang 6

MSV

hoten

dtb

next

MSV hoten dtb next

MSV hoten dtb next

* Ví dụ:

struct SV

{

int MSV;

char hoten[25];

float dtb;

} ;

struct DNode

{

SV info;

struct SV *next;

struct SV *previous;

} ;

struct DList

{ DNode *Head; DNode *Tail; } ;

DList DQ;

Danh sách liên kết

66

2 Các thao các trên danh sách kép

#   Đối với danh sách kép có các thao tác cơ bản sau:

  Tạo danh sách

  Chèn một phần tử

  Hủy một phần tử

  Tìm kiếm phần tử

  Duyệt danh sách

  Sắp xếp danh sách theo thành phần dữ liệu

Danh sách liên kết

67

a Tạo danh sách

! Gồm:

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

Danh sách liên kết

68

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(”Ko du bo nho”);

exit(1);

}

p -> infor = x;

p -> next = NULL;

p -> previous = NULL;

return p;

}

Danh sách liên kết

70

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

! 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

Danh sách liên kết

Chèn thêm vào trước phần tử q:

#   Nếu phần tử q khác rỗng " có tồn tại phần tử q

p = q -> previous //Tạo phần tử p đứng trước q

new_element -> next = q

new_element -> previous = p

q -> previous = new_element

Cài đặt:

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;

} }

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

Trang 7

DQ.Tail

DQ.Head

DQ.Tail

DQ.Head

DQ.Tail

Danh sách liên kết

82

Hủy một phần tử đứng trước phần tử q:

DQ.Tail

DQ.Head

Danh sách liên kết

89

Cài đặt xóa phần tử đứng trước phần tử q

void RemoveBefore (DLIST &DQ, Dnode *q)

{ Dnode *p;

if ( q = = NULL ) MoveLast(DQ);

else //Co phan tu q

{

if (q = = DQ.Head) //Phần tử q là phần tử đầu

{ 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);

} }

Danh sách liên kết

90

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

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

Danh sách liên kết

e Sắp xếp các phần tử của danh sách:

void Sort_Inter(D_LIST &DQ)

{ Dnode *p,*q;

p = DQ.Head;

q = p -> next;

while (p!=NULL) {

q = p -> next;

while ( q != NULL) {

if ( p -> info > q -> info )

Hoandoi( p->info , q->info );

q = q -> next;

}

p = p -> next;

} }

Danh sách liên kết

95

Bài tập áp dụng

!  Cho thông tin của cán bộ gồm: mã cán bộ, họ tên, ngày

sinh, hệ số lương, phụ cấp và thành tiền (=hệ số lượng *

1050000 + phụ cấp)

!  Thực hiện các yêu cầu sau:

–  Áp dụng mảng Định nghĩa các thao tác sau:

!  In lại toàn bộ danh sách cán bộ

!  SX DSCB tăng dần theo tổng lương

–  Viết chương trình thực hiện các chức năng trên

Danh sách liên kết

96

Bài tập thực hành (y/c chi tiết)

!  Khai Báo CTDL DSLK chứa Cán bộ gồm: MCB, Hoten, Tuoi, HSL,

PC, TT(=HSL* 1.050.000 + PC)

!  Định nghĩa các CTC sau:

!  Áp dụng lần lượt các CTC trên dưới dạng menu lựa chọn:

–  0 Thoát

–  1 Tạo DSCB 2 In lại DSCB

–  3 Tìm kiếm CB theo mã nào đó 4 Đếm số CB lương từ 2 đến 3 triệu

–  5 Tính tổng lương của các cán bộ 6 …

Nhập một cán bộ Tính tổng lương của các CB

In một cán bộ SX DSCB tăng dần theo tổng lương

Nhập 1 DSCB In DS CB có tuổi dưới 20

In DSCB Cho biết Họ tên của CB có lương cao nhất

Tìm kiếm một CB có mã nào đó Chèn thêm một cán bộ cvaof sau cán bộ có mã là x nào đó

Đếm số CB có lương từ 2 đến 3 triệu

*Bài tập áp dụng

!  Thông tin về nhân viên gồm: mã số nhân viên, họ tên, ngày sinh, tổng lương

!  Thực hiện các yêu cầu sau:

–  a Khai báo CTDL của DSLK đôi để quản lý DSNV

–  Thực hiện các thao tác trên danh sách

!  b Thêm một nhân viên vào đầu danh sách liên kết kép trên

!  c In lại toàn bộ danh sách nhân viên ra màn hình

!  d Tính tổng lương của tất cả các nhân viên trong DS

!  e Hủy một nhân viên khỏi đầu danh sách

!  f In danh sách nhân viên có mức lương cao nhất

!  g Sắp xếp DSNV theo tứ tự giảm dần của lương

98

Cài đặt chương trình

!  Cho thông tin của Nhân viên gồm: mã nhân viên, họ tên, tuổi, HSL, PC (Luong = (HSL+PC)*1050000)

!  Cài đặt CT bằng ngôn ngữ C để quản lý DSNV dưới dạng DSLK Đơn với các yêu cầu sau:

–  Tạo danh sách

–  Chèn thêm vào danh sách một số phần tử (đầu và cuối)

–  Hiển thị lại toàn bộ danh sách

–  Hiển thị ds cán bộ có lương trên 2 triệu

–  Tìm kiếm một nhân viên theo mã nào đó

–  Chèn thêm một nhân viên vào sau nhân viên q nào đó

–  Tính tổng lương của các nhân viên

–  Sắp xếp danh sách NV theo lương giảm dần

–  …

!  Áp dụng chương trình bằng các menu lựa chọn 99

Trang 8

Bài tập áp dụng

!   Cài đặt chương trình BTL dưới dạng DSLK với một số yêu cầu cơ

bản:

–  Tạo danh sách

–  Hiển thị toàn bộ danh sách

–  Chèn đầu

–  Xóa đầu

–  Tìm kiếm

–  Sắp xếp

!   Nộp bài

–   Hạn: Muộn nhất 20h -ngày 30/1/2013

–   Gửi mail: trinhxuan@gmail.com

–   subject: CTDL - CT6 - Họ tên sinh viên - Lớp

–   Đính kèm file

!   File đặt theo nguyên tắc: Tên sinh viên_Lớp.CPP

Danh sách liên kết

10

0

Bài tập về nhà – 6/10/2014

!  Mỗi nhóm chọn ra một đối tượng cần quản lý của bài toán

!  Cài đặt quản lý đối tượng đó bằng mảng, gồm tối thiểu:

–  Nhập & in DS - Tìm kiếm –  Tính tổng & tính tổng có điều kiện - Sắp xếp –  Đếm & đếm có điều kiện - Phần tử lớn nhất và nhỏ nhất

=> Áp dụng các yêu cầu trên

!  Yêu cầu nộp bài:

–  Mỗi nhóm nộp 1 bài, trong đầu chương trình ghi rõ thông tin nhóm và bài toán của mình

–  Gửi mail: trinhxuan@gmail.com trước 17h – ngày 12/10/2014

–  Subject: CTDL – BTL – Mảng - <Thứ tự nhóm>

–  Tên file: CTDL_<Thứ tự nhóm> Danh sách liên kết

10

1

Bài tập về nhà buổi 4 Đọc DS LK đơn

!  Khai báo CTDL

!  Khởi tạo danh sách

!  Thêm phần tử

!  Xóa

!  Duyệt

!  Sắp xếp

Mỗi phần xác định:

!  Ý tưởng

!  Các bước

!  Minh họa

!  Cài đặt

Danh sách liên kết

10

2

Bài tập về nhà buổi 5

Đọc DS LK kép

!  Khai báo CTDL

!  Khởi tạo danh sách

!  Thêm phần tử

!  Xóa

!  Duyệt

!  Sắp xếp

Mỗi phần xác định:

!  Ý tưởng

!  Các bước

!  Minh họa

!  Cài đặt

Danh sách liên kết

10

3

Bài tập về nhà buổi 6 Đọc Stack - Queue

–  Định nghĩa –  Cài đặt –  Ứng dụng

! Queue

–  Định nghĩa

–  Cài đặt

–  Ứng dụng

Danh sách liên kết

10

4

Ngày đăng: 11/05/2021, 01:26

TỪ KHÓA LIÊN QUAN