1. Trang chủ
  2. » Giáo Dục - Đào Tạo

Danh sách liên kết

52 12 0

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

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 52
Dung lượng 295 KB

Nội dung

Danh sách liên kết (Linked List)... Lê Mậu Long 6.[r]

(1)

Lê Mậu Long

(2)

Lê Mậu Long

(3)

Lê Mậu Long

Giới thiệu

• Định nghĩa: Là danh sách bao gồm các

(4)

Lê Mậu Long

Các thao tác danh sách

• Khởi tạo danh sách rỡng • Kiểm tra danh sách rỡng? • Chèn phần tử vào danh sách • Xóa phần tử danh sách

• Tìm kiếm phần tử danh sách • Khởi đầu từ đầu danh sách

• Lấy dữ liệu phần tư

• Chuyển sang phần tử kế tiếp • Hết danh sách

(5)

Lê Mậu Long

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

• Là danh sách mà mỡi phần tử có mối liên kết để kết nối với phần tử kế tiếp

• Cài đặt: dựa trỏ, bao gờm:

• 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

(6)

Lê Mậu Long

Mô tả kiểu dữ liệu

typedef struct nodet {

elem data;

struct nodet *next; } node;

(7)

Lê Mậu Long

typedef struct {

nodeptr head, pos, rear; int count;

} list;

(8)

Lê Mậu Long Khởi tạo danh sách rỗng

Gán

– head, pos và rear = NULL – count =

// Hàm khởi tạo

void createlist(list &l) {

l.head = l.pos = l.rear = NULL; l.count = 0;

(9)

Lê Mậu Long Kiểm tra danh sách rỡng?

• Kiểm tra sớ phần tử = 0

int emptylist(list l) {

(10)

Lê Mậu Long 10 Chèn phần tử x vào danh sách – cục bợ

(local)

• Cấp phát bợ nhớ cho newp và gán dữ liệu • Chèn ở đầu ds (p==NULL)

newp->next = head; head = newp;

head pos rear

(11)

Lê Mậu Long 11

• Chèn sau phần tử p (p!=NULL)

newp->next = p->next; p->next = newp;

head pos p rear

(12)

Lê Mậu Long 12

• Trường hợp chèn ći (newpnext == NULL)

• Thay đởi rear

rear = newp;

head pos p rear

(13)

Lê Mậu Long 13

void insertlist(list &l, elem &x, nodeptr p) {

nodeptr newp = new node;

memcpy(&newp->data, &x, sizeof(elem)); if (p==NULL)

{

newp->next = l.head; l.head = newp;

} else {

newp->next = p->next; p->next = newp;

}

if (newp->next == NULL) l.rear = newp;

(14)

Lê Mậu Long 14

Các hàm chèn phần tử – toàn cục (global)

• Chèn đầu danh sách

void inserthead(list &l, elem &x) {

insertlist(l, x, NULL); }

• Chèn vị trí hiện hành

void insertpos(list &l, elem &x) {

insertlist(l, x, l.pos); }

• Chèn ći danh sách

void insertrear(list &l, elem &x) {

(15)

Lê Mậu Long 15 Xoá phần tử danh sách – cục bộ • Xoá phần tử đầu danh sách (p=NULL)

t = head;

head = t->next;

• Xoá phần tử sau p (p!=NULL)

t = p->next;

p->next = t->next;

p

head p t rear

head rear

(16)

Lê Mậu Long 16 void deletelist(list &l, nodeptr p)

{ nodeptr t; if (p==NULL) {

t = l.head;

l.head = t->next; }

else {

t = p->next;

p->next = t->next; }

if (t->next == NULL) l.rear = p; delete t;

(17)

Lê Mậu Long 17

Các hàm xóa phần tử – toàn cục

• Xóa phần tử đầu danh sách void deletehead(list &l) {

deletelist(l, NULL); }

• Xóa phần tử tại vị trí hiện hành void deletepos(list &l)

{

(18)

Lê Mậu Long 18

Tìm kiếm DS

X=5

1. Khởi đầu từ đầu danh sách (pos = NULL; c = head) 2. Khi chưa hết ds và chưa tìm thấy

Chuyển sang phần tử kế tiếp (pos = c; c = cnext)

head pos c rear

(19)

Lê Mậu Long 19

Tìm kiếm DS – bản nháp

int searchlist(list &l, elem x) {

nodeptr c = l.head; l.pos = NULL;

while (c!=NULL && x!=c->data) {

l.pos = c; c = c->next; }

(20)

Lê Mậu Long 20

Tìm kiếm DS – viết lại

int searchlist(list &l, elem x, int (*comp)(elem, elem)) {

nodeptr c = l.head; l.pos = NULL;

while (c!=NULL && comp(x, c->data)!=0) {

l.pos = c; c = c->next; }

(21)

Lê Mậu Long 21

Tìm kiếm DS có thứ tư

int searchorderlist(list &l, elem x, int (*comp)(elem, elem)) {

nodeptr c = l.head; l.pos = NULL;

while (c!=NULL && comp(x, c->data)>0) {

l.pos = c; c = c->next; }

if (c!=NULL && comp(x, c->data)<0) return 0;

(22)

Lê Mậu Long 22

Ví du int searchorderlist(list &l, elem x, int

(*comp)(elem, elem)) {

nodeptr c = l.head; l.pos = NULL;

while (c!=NULL && comp(x, c->data)>0) {

l.pos = c; c = c->next; }

if (c!=NULL && comp(x, c->data)<0) return 0;

return c!=NULL; }

// Hàm so sánh khoá int ss(int x, int y)

{

return x-y; }

//Đoạn chương trinh nhập dãy createlist(l);

cout<<"\nNhap day:"; do {

cin>>x; if (x>0) {

searchorderlist(l, x, ss); insertpos(l, x);

}

(23)

Lê Mậu Long 23 • Khởi đầu từ đầu danh sách

void start(list &l) {

l.pos = l.head; }

• Chuyển sang phần tử kế tiếp void skip(list &l)

{

if (l.pos == NULL) l.pos = l.head; else

(24)

Lê Mậu Long 24

• Kiểm tra hết danh sách int eol(list l)

{

return l.pos == NULL; }

• Lấy dữ liệu phần tử

void getdata(list l, elem &x) {

memcpy(&x, &l.pos->data, sizeof(elem)); }

• Sớ phần tử danh sách int nolist(list l)

{

(25)

Lê Mậu Long 25

Ngăn xếp (Stack)

• Là cấu trúc bao gờm các phần tử được truy xuất theo nguyên tắc “vào sau, trước” (Last In, First Out – LIFO)

Ví dụ: Chồng đĩa, đổi số nhị phân

(26)

Lê Mậu Long 26

Các thao tác Stack

4 thao tác bản stack

• Khởi tạo stack rỡng: CreateStack(s)

• Kiểm tra stack rỡng: EmptyStack(s)

• Đưa phần tủ vào Stack: Push(s, x)

(27)

Lê Mậu Long 27

Cài đặt sở mảng

• Sử dụng

– Mảng e[Max] phần tử kiểu elem

(elementtype)

– Chỉ số top để chỉ đỉnh stack (nơi đưa vào, lấy ra)

• Tạo tập tin Stack.cpp: typedef struct {

elem e[Max]; int top;

} stack;

1 1 0

top

e

(28)

Lê Mậu Long 28

Các thao tác Stack

Khởi tạo stack s rỗng

void createstack(stack &s) {

s.top = -1; }

Kiểm tra stack s rỗng?

int emptystack(stack s) {

(29)

Lê Mậu Long 29 • Đưa phần tử x vào stack s

void push(stack &s, elem &x) {

if (s.top==Max-1) exit(0);

memcpy(&s.e[++s.top], &x, sizeof(elem)); }

Lấy phần tử x khỏi stack s void pop(stack &s, elem &x)

{

if (s.top==-1) exit(0);

(30)

Lê Mậu Long 30

Ví dụ: Đổi số nhị phân

#define Max 32

#include <iostream.h> typedef int elem;

#include "stack.cpp" void main()

{

int i, n; stack s;

cout<<"\nNhap so can doi:"; cin>>n;

createstack(s); while (n>0) {

i = n%2; push(s, i); n = n/2; }

cout<<"Ket qua dang nhi phan :"; while (!emptystack(s))

{

pop(s, i); cout<<i; }

(31)

Lê Mậu Long 31

(32)

Lê Mậu Long 32

Định nghĩa

• Một định nghĩa gọi là đệ qui nếu nó được định nghĩa chính nó cách trực tiếp hay gián tiếp

• Đệ qui ln gờm phần

(33)

Lê Mậu Long 33 Ví du 0 )! ( !        n n n n n 0 0 . 1        n n x x

xn n

(34)

Lê Mậu Long 34

Giai thừa

long gt(int n) {

if (n==0) return 1; return n*gt(n-1); }

void main() {

(35)

Lê Mậu Long 35

Khử bỏ đệ qui

• Sử dung Stack

• Đệ qui thay bằng:

– Hàm đệ qui: Vòng lặp

– Lời gọi đệ qui: Push các giá trị cuc – Thực hiện đệ qui: Pop các giá trị cuc

(36)

Lê Mậu Long 36

Bài toán Tháp Hanoi

#include <iostream.h>

void chuyen(int n, char A, char B, char C) {

if (n==1)

cout<<"\nChuyen "<<A<<" qua "<<C; else

{

chuyen(n-1, A, C, B); chuyen(1, A, ' ', C); chuyen(n-1, B, A, C); }

}

void main() {

cout<<"\n============ De qui ==============="; chuyen(3, 'a', 'b', 'c');

(37)

Lê Mậu Long 37

Bài toán Tháp Hanoi không đệ qui

1 Khởi tạo stack s rỗng

2 Push (3, ‘A’, ‘B’, ‘C’) vào s 3 Lặp

– Pop khỏi s (n, A, B, C); – Nếu n=1

• cout<<"\nChuyen "<<A<<" qua "<<C;

– Ngược lại

• Push (n-1, B, A, C) vào s • Push (1, A, ‘ ‘, C) vào s • Push (n-1, A, C, B) vào s

(38)

Lê Mậu Long 38

Cài đặt sở trỏ

• Cài đặt tương tư danh sách liên kết đơn với thao tác

– Chèn đầu danh sách

– Lấy ở đầu danh sách

s

(39)

Lê Mậu Long 39 • Tạo tập tin Stack.cpp:

typedef struct nodet { elem data;

struct nodet *next; } node;

typedef node *stack;

void createstack(stack &s) {

(40)

Lê Mậu Long 40

int emptystack(stack s) {

return s==NULL; }

void push(stack &s, elem &x) {

stack newp = new node;

memcpy(&newp->data, &x, sizeof(elem)); newp->next = s;

s = newp; }

newp

(41)

Lê Mậu Long 41 void pop(stack &s, elem &x)

{

stack t = s;

if (s==NULL) exit(0);

memcpy(&x, &s->data, sizeof(elem)); s = s->next;

delete t; }

Chạy lại chương trình đổi nhị phân, nhận xét?

s

(42)

Lê Mậu Long 42

Hàng đợi (Queue)

• Là cấu trúc bao gờm các phần tử được truy xuất

theo nguyên tắc “vào trước, trước” (First In, First Out – FIFO)

(43)

Lê Mậu Long 43

Các thao tác Queue

4 thao tác bản queue

• Khởi tạo queue rỡng: CreateQueue(q)

• Kiểm tra queue rỡng: EmptyQueue(q)

• Đưa phần tủ vào queue : AddQueue(q, x)

(44)

Lê Mậu Long 44 Cài đặt sở mảng

• Sử dụng

– Mảng e[Max] phần tử kiểu elem (elementtype) – Chỉ số

front để chỉ đầu hàng đợi (nơi lấy ra) – rear để chỉ cuối hàng đợi (nơi đưa vào)

Hai chỉ sớ front và rear tăng xoay vòng • Tạo tập tin Queue.cpp:

(45)

Lê Mậu Long 45

Các thao tác Queue

Khởi tạo queue q rỗng

void createqueue(queue &q) {

q.front = q.rear = 0; }

Kiểm tra queue q rỗng?

int emptyqueue(queue q) {

(46)

Lê Mậu Long 46

Đưa phần tử x vào queue q

void addqueue(queue &q, elem &x) {

int nr = (q.rear + 1) % Max; if (nr == q.front) exit(0);

memcpy(&q.e[q.rear], &x, sizeof(elem)); q.rear = nr;

}

Lấy phần tử x khỏi queue q

void removequeue(queue &q, elem &x) {

if (q.front == q.rear) exit(0);

memcpy(&x, &q.e[q.front], sizeof(elem)); q.front = (q.front + 1) % Max;

(47)

Lê Mậu Long 47

Ví du: Radix sort

• Sắp xếp dãy sớ ngun dương tăng dần

71, 32, 53, 70, 50 , 63, 84, 15, 26, 19, 8, 37, 17, 46, 98, 21

8, 15, 17, 19, 21, 26, 32, 37, 46, 50, 53, 63, 70, 71, 84, 98

70 50 71 21 32 53 63 84

0

(48)

Lê Mậu Long 48

Cài đặt sở trỏ

• Cài đặt tương tư danh sách liên kết đơn với thao tác

– Chèn cuối danh sách – Lấy ở đầu danh sách

front

remove add

(49)

Lê Mậu Long 49 • Tạo tập tin Queue.cpp:

typedef struct nodet { elem data;

struct nodet *next; } node;

typedef node *nodeptr; typedef struct {

nodeptr front, rear; } queue;

void createqueue(queue &q) {

(50)

Lê Mậu Long 50

int emptyqueue(queue q) {

return q.front == NULL; }

void addqueue(queue &q, elem &x) {

nodeptr newp = new node;

memcpy(&newp->data, &x, sizeof(elem)); newp->next = NULL;

if (q.front == NULL) q.front = newp; else

q.rear->next = newp; q.rear = newp;

}

newp

(51)

Lê Mậu Long 51

void removequeue(queue &q, elem &x) {

nodeptr t = q.front;

if (q.front == NULL) exit(0); q.front = t->next;

memcpy(&x, &t->data, sizeof(elem)); delete t;

}

front

(52)

Lê Mậu Long 52

Ngày đăng: 27/04/2021, 17:57

w