Stack and Queue

GV : Phạm Ngọc Nam Khoa : CNTT Email: tgtnam3012@gmail.com

Cấu Trúc Dữ Liệu & Giải Thuật

Stack (Ngăn xếp)

Giới thiệu

Các thao tác cơ bản

Các ứng dụng

2

Queue (Hàng Đợi)

Giới thiệu

Các thao tác cơ bản

Ứng dụng

3

Giới thiệu

Một số hình ảnh thông dụng  Một chồng Sách Vở ở trên bàn

 Một chồng Đĩa

4

 Nhận xét gì từ các ví dụ trên?

Giới thiệu

Định nghĩa:  Ngăn xếp là cấu trúc chứa các đối tượng làm việc theo cơ chế “ vào sau ra trước” (Last in First out).  đối tượng có thể được thêm vào bất kỳ lúc nào, nhưng chỉ có đối tượng vào sau cùng mới được phép lây ra khỏi ngăn xếp.

5

Các thao tác trên ngăn xếp

6

 Lưu trữ Ngăn Xếp.  khởi tạo Stack rỗng  Kiểm tra Ngăn Xếp rỗng.  Thêm một phần tử vào Ngăn Xếp.  Lấy một phần tử ra khỏi Ngăn Xếp.  Lấy thông tin của phần tử đầu Ngăn Xếp.

Lưu trữ Stack bằng DSLK

7

 Thêm vào đầu danh sách(AddHead): phần tử mới thêm nằm ở đầu danh sách  Truy xuất danh sách: Truy xuất phần tử nằm ở đầu trước. => Thích hợp với tính chất của Ngăn Xếp.

Lưu trữ Stack bằng DSLK

8

Lưu trữ Stack bằng DSLK

 khai báo cấu trúc 1 phần tử trong Stack

struct NodeStack{ dataType data; NodeStack *pNext;

};  khai báo cấu trúc Stack

struct Stack{ int count; NodeStack *pHead;

};

9

 Cài đặt

Khởi tạo Stack

 Cài đặt: void InitStack(Stack &s) {

s.count = 0; s.pHead==NULL)

10

}

Kiểm tra Stack Rỗng

 Ngăn xếp rỗng khi không chứa phần tử nào.  Cài đặt: bool IsEmpty(const Stack s) {

if(s.pHead==NULL) return true;

return false;

11

}

Kiểm tra Stack đầy

bool IsFull(const Stack &s) {

NodeStack *pNew=new NodeStack; if(pNew == NULL)// nếu ko tạo đc stack đầy

return true; return false;// stack ko đầy

}

12

 Ngăn xếp đầy khi không thể cấp phát thêm vùng nhớ.  Khi thêm 1 phần tử vào Ngăn Xếp, nếu không cấp phát được vùng nhớ => Thông báo ngăn xếp đầy.

Thêm một phần tử

 Giải Thuật:

13

 Tương tự thao tác thêm đầu(AddHead).  Nếu không thêm được(do không cấp phát được vùng nhớ) trả về giá trị cho biết ngăn xếp đầy.  Cài đặt:

Thêm một phần tử

int Push(Stack &s, int x) {

NodeStack *pNew = new NodeStack; if(pNew == NULL)

return 0;// ko cấp phát được

vùng nhớ, stack đầy

pNew -> data = x; pNew -> pNext = NULL; if(s.pHead == NULL){

s.pHead = pNew; return 1;

} else{

pNew -> pNext = s.pHead; s.pHead = pNew; return 1;

}

14

}

 Cài đặt:

Thêm một phần tử

int Push(Stack &s, int x) {

if(IsFull(s))

return 0;// stack đầy ko thêm đc

NodeStack *pNew = new NodeStack; pNew -> data = x; pNew -> pNext = s.pHead; s.pHead = pNew; s.count ++; return 1; // thêm thành công

}

15

 Cài đặt cách khác

Lấy một phần tử ra khỏi ngăn xếp

 kiểm tra Ngăn Xếp rỗng hay không  Nếu không:

 Ghi nhận giá trị của phần tử ở đầu Ngăn Xếp.  Xóa phần tử đầu ra khỏi Ngăn Xếp.  Trả về giá trị đã ghi nhận.

16

 Lấy đối tượng ở đầu Ngăn Xếp ra khỏi Ngăn Xếp và trả về giá trị của đối tượng đó.  Nếu Stack rỗng báo lỗi.  Thuật toán:

Lấy một phần tử ra khỏi ngăn xếp

DataType * Pop(Stack &s) {

// Kiểm tra Ngăn Xếp rỗng if(……………….)

return 0;

// Ghi nhận giá trị đầu Ngăn Xếp datatype x= l.pHead->data; // Xóa đầu Ngăn Xếp / / Trả về giá trị đã ghi nhân return …;

}

17

 Cài đặt

Lấy một phần tử ra khỏi ngăn xếp

int Pop(Stack &s) {

if(s.pHead = = NULL)

return 0; // stack rỗng không lấy ra được

NodeStack * pNew = s.pHead; s.pHead = pNew ->pNext; delete pNew ; s.count --; return 1; // xóa thành công

}

18

 Cài đặt

Lấy một phần tử ra khỏi ngăn xếp

int Pop(Stack &s, int &outdata) {

if(IsEmpty(s))

return 0; // stack rỗng không lấy ra được

NodeStack * pNew = s.pHead; outdata = pNew -> data; s.pHead = pNew ->pNext; delete pNew ; s.count --; return 1; // lấy ra thành công

}

19

 Cài đặt

Các ứng dựng của Stack

20

 Lưu vết trong các giải thuật “back-tracking”  Bài toán “N quân hậu”

Queue (Hàng Đợi)

Giới thiệu

Các thao tác cơ bản

Ứng dụng

21

21

Giới thiệu

 Queue là cấu trúc chứa các đối tượng làm việc theo qui tắc “ Vào sau ra trước(FIFO)”.  Các đối tượng có thể được thêm vào hàng đợi bất kì lúc nào nhưng chỉ có đối tượng thêm vào đầu tiên mới được lấy ra khỏi hàng đợi.

22

 Việc thêm vào diễn ra ở cuối, việc lấy ra diễn ra ở đầu.

Các thao tác trên Queue

23

 Lưu trữ Queue.  kiểm tra Queue rỗng Thêm một phần tử vào cuối Queue.  Lấy một phần tử ở đầu ra khỏi Queue.  Lấy thông tin của đối tượng ỏ đầu Queue.

Lưu trữ Queue bằng DSLK

24

 Khai báo hàng đợi như một DSLK với phần tử đầu (pHead) và đuôi (pTail).  Phần tử đầu: nơi lấy dữ liệu hàng đợi ra. Phần tử đuôi: nơi thêm phần tử vào

Kiểm tra Queue rỗng

bool IsEmpty(NodeQueue *q) {

if(q->pHead = = NULL)

return true;

return false;

}

25

 Hàng đợi rỗng khi không có phần tử nào (DS rỗng)  Cài đặt

Kiểm tra Queue đầy

{

if(…) …

}

26

 Hàng đợi đầy khi không thể cấp phát thêm vùng nhớ.  Khi thêm 1 phần tử vào hàng đợi, nếu không cấp phát được vùng nhớ -> Thông báo hàng đợi đầy  Cài đặt bool IsFull(…)

Thêm phần tử vào cuối Queue

 Tương tự thao tác thêm cuối.

 Nếu không thêm được (do không cấp phát được vùng nhớ) trả về giá trị cho biết hàng đợi đầy  Cài đặt: int EnQueue (NODE *&pHead, NODE *&pTail, Data x) {

//tạo 1 nút mới if()

return 0;

//thêm nút mới vào đuôi return 1;

}

27

 Giải thuật:

Lấy phần tử đầu ra khỏi Queue

 Ghi nhận giá trị của phần tử ở đầu hàng đợi.  Xóa phần tử đầu ra khỏi hàng đợi.  Trả về giá trị đã ghi nhận.

 Cài đặt: Data DeQueue(NODE*& pHead, NODE*& pTail) {

//kiểm tra Queue rỗng? if(…)

return …; ////ghi nhận giá trị đầu Queue Data x = pHead -> data; //xóa đầu Queue… //trả về giá trị đã ghi nhận return _______;

28

}

 Giải thuật:

Lấy phần tử đầu Queue

 Chỉ lấy thông tin của đối tượng đầu hàng đợi mà không

hủy đối tượng khỏi hàng đợi.

 Cài đặt:

 Kiểm tra hàng đợi rỗng?  Trả về giá trị của phần tử đầu hàng đợi.

Data DeQueue(NODE*& pHead) {

….

}

29

 Giải thuật:

Các ứng dựng của Queue

 Sử dụng giải 1 số bài toán lý thuyết đồ thị.

30