stack & queue
TRANSCRIPT
NỘI DUNG Kiểu dữ liệu Stack & Queue Cài đặt Stack & Queue Các cơ chế an toàn Ứng dụng thực tiễn
DANH SÁCH Danh sách
Dãy hữu hạn phần tử Các thao tác: tạo mới, hủy, thêm, xóa, …
Danh sách và mảng Ví dụ minh họa
DANH SÁCH ĐẶC, DANH SÁCH LIÊN KẾT Danh sách đặc: dùng mảng cài đặt Danh sách liên kết: dùng cấu trúc liên kết So sánh về mặt sử dụng bộ nhớ So sánh về mặt thao tác
1 3 5 8 …
1 o 3 o 5 o 8 o
NULL
max_count = 100
1
DANH SÁCH HẠN CHẾ Danh sách: Thêm, xóa ở vị trí bất kỳ Stack: Thêm, xóa từ một đầu Queue: Thêm đầu này, xóa đầu kia Dùng List như Stack hoặc Queue?
3 7 9
5
1 3 7 9571 3 9
NGĂN XẾP Stack: Thêm, xóa phần tử từ một đầu (top) Stack là cấu trúc LIFO (Last In First Out)
HÀNG ĐỢI Queue: Thêm vào đầu này, lấy ra đầu kia Queue là cấu trúc FIFO (First In First Out)
1234
4
125 345
CÀI ĐẶT Danh sách đặc Danh sách liên kết
CÀI ĐẶT NGĂN XẾP BẰNGDANH SÁCH ĐẶC (Stack.h)const max_stack = 100; // kích thước tối đatemplate <class Stack_Element> // Stack_Element=int, double, string, Employee class Stack{private: // định nghĩa cấu trúc dữ liệuint count; // vị trí top, số phần tửStack_Entry entry[max_stack];public: // định nghĩa các thao tác trừu tượngStack(); // hàm khởi tạo mặc địnhbool empty() const;bool full() const;bool push(const Stack_Entry &item);bool pop();};
count
CÀI ĐẶT NGĂN XẾP BẰNGDANH SÁCH ĐẶC (Stack.cpp)template <class Stack_Element>Stack<Stack_Element>::Stack(){
count = 0;}
bool Stack<Stack_Element>::push(const Stack_Entry &item){
bool outcome = true;if full()
outcome = false;else
entry[count++] = item;return outcome;
}
count
count
item
count
item
item
CÀI ĐẶT NGĂN XẾP BẰNGDANH SÁCH ĐẶC (Stack.cpp)template <class Stack_Element>bool Stack<Stack_Element>::pop(){
bool outcome = true;if empty()
outcome = false;else
count--;return outcome;
}
count
count
count
CÀI ĐẶT NGĂN XẾP BẰNGDANH SÁCH ĐẶC (Stack.cpp)template <class Stack_Element>bool Stack<Stack_Element>::empty() const{
return (count == 0);}template <class Stack_Element>bool Stack<Stack_Element>::full() const{
return (count == max_stack);}
count
count=max_stack
.
.
.
CÀI ĐẶT NGĂN XẾP BẰNGDANH SÁCH LIÊN KẾTtemplate <class Node_Entry>struct Node{Node_Entry entry;Node<Node_Entry> *next;Node(); // hàm khởi tạo mặc địnhNode(Node_Entry item, Node<Node_Entry> *link=NULL);};template <class Node_Entry>Node<Node_Entry>::Node(){next = NULL;}template <class Node_Entry>Node<Node_Entry>::Node(Node_Entry item, Node<Node_Entry> *link){entry = item;next = link;}
entrynext
item entry
CÀI ĐẶT NGĂN XẾP BẰNGDANH SÁCH LIÊN KẾTtemplate <class Node_Entry>class Stack {private:
Node<Node_Entry> *top_node;public:
Stack(); // hàm khởi tạo mặc địnhbool empty() const;//bool full() const;bool push(const Node_Entry &item);bool pop();
};
entry
CÀI ĐẶT NGĂN XẾP BẰNGDANH SÁCH LIÊN KẾTtemplate <class Node_Entry>Stack<Node_Entry>::Stack(){
top_node = NULL;}
template <class Node_Entry>bool Stack<Node_Entry>::empty() const{
return (top_node == NULL);}
entry
CÀI ĐẶT NGĂN XẾP BẰNGDANH SÁCH LIÊN KẾTtemplate <class Node_Entry>bool Stack<Node_Entry>::push(const Node_Entry &item){
Node<Node_Entry> *new_top = new Node<Node_Entry>(item, top_node);if (new_top == NULL)
return false;top_node = new_top;return true;
}
entry entry entryitem
CÀI ĐẶT NGĂN XẾP BẰNGDANH SÁCH LIÊN KẾTtemplate <class Node_Entry>bool Stack<Node_Entry>::pop(){Node<Node_Entry> *old_top = top_node;if (empty())return false;top_node = old_top->next; // new top_nodedelete old_top;return true;}
entry entry entryentry
CÀI ĐẶT HÀNG ĐỢI BẰNG DANH SÁCH ĐẶC Mảng tuyến tính (linear array) Mảng vòng (circular array) Hàng đợi trong thực tế?
0 1 2 3
front
4 5 6
rear
0 1 2 3
front
4 5 6 7 8 9
rear
7 8 9
rear
rear
0
CÀI ĐẶT HÀNG ĐỢI BẰNG DANH SÁCH ĐẶC Hàng đợi rỗng Hàng đợi đầy
frontrear front
frontrear rear
CÀI ĐẶT HÀNG ĐỢI BẰNG DANH SÁCH ĐẶCconst max_queue = 100;template <class Entry_Element>class Queue{private:int count; // số phần tửint front; // vị trí đầu hàng đợiint rear; // vị trị cuối hàng đợiEntry_Element entry[max_queue]; public:Queue(); // hàm khởi tạo mặc địnhbool empty() const;bool full() const;bool serve(); // dequeuebool append(const Queue_Entry &item); // enqueue};
item item item item
count = 4
frontrear
CÀI ĐẶT HÀNG ĐỢI BẰNG DANH SÁCH ĐẶCtemplate <class Queue_Element>Queue<Queue_Element>::Queue(){count = 0;front = 0;rear = max_queue - 1;}
front rear
CÀI ĐẶT HÀNG ĐỢI BẰNG DANH SÁCH ĐẶCtemplate <class Queue_Element>bool Queue<Queue_Element>::empty() const{return (count == 0);}
template <class Queue_Element>bool Queue<Queue_Element>::full() const{return (count == max_queue);}
front rear
CÀI ĐẶT HÀNG ĐỢI BẰNG DANH SÁCH ĐẶCtemplate <class Queue_Element>bool Queue<Queue_Element>::append(const Queue_Element &item) {if (full()) // queue đầyreturn false;count++;//rear = ((rear + 1) == max_queue) ? 0 : (rear + 1);rear = (rear + 1) % max_queue;entry[rear] = item;return true;}
front rear
item
rear
item
rear rear
CÀI ĐẶT HÀNG ĐỢI BẰNG DANH SÁCH ĐẶCtemplate <class Queue_Element>bool Queue<Queue_Element>::serve(){if (empty())return false;count--;//front = ((front + 1) == max_queue) ? 0 : (front + 1);front = (front + 1) % max_queue;return true;}
front rearfront front
CÀI ĐẶT HÀNG ĐỢI BẰNG DANH SÁCH LIÊN KẾTtemplate <class Node_Entry>class Queue{private:Node<Node_Entry> *front;Node<Node_Entry> *rear;public:Queue(); // hàm khởi tạo mặc địnhbool empty() const;//bool full() const;bool append(const Node_Entry &item);bool serve();};
Node_Entry
front rear
CÀI ĐẶT HÀNG ĐỢI BẰNG DANH SÁCH LIÊN KẾTtemplate <class Node_Entry>Queue<Node_Entry>::Queue(){front = NULL;rear = NULL;}
template <class Node_Entry>bool Queue<Node_Entry>::empty(){return (front == NULL);}
CÀI ĐẶT HÀNG ĐỢI BẰNG DANH SÁCH LIÊN KẾTtemplate <class Node_Entry>bool Queue<Node_Entry>::append(const Node_Entry &item){Node<Node_Entry> *new_rear = new Node<Node_Entry>(item);if (new_rear == NULL)return false;if (rear == NULL){front = new_rear;rear = new_rear;}else{rear->next = new_rear;rear = new_rear;}
}
Node_Entry
front rear
item
item
CÀI ĐẶT HÀNG ĐỢI BẰNG DANH SÁCH LIÊN KẾTtemplate <class Node_Entry>bool Queue<Node_Entry>::serve(){if (empty())return false;Node<Node_Entry> *old_front = front;front = old_front->next;if (front == NULL) // danh sách có 1 phần tửrear = NULL;delete old_front;return true;
}
Node_Entry
Node_Entry
LỖI THƯỜNG GẶP ‘Không thể lấy nước từ bình rỗng’ Con trỏ đến đối tượng đã bị hủy Chưa qua cầu đã rút ván
p NULL
del
top
top
CƠ CHẾ AN TOÀN
Tại sao cấu trúc liên kết không an toàn? Bộ nhớ không tự hủy Truyền tham biến
Các cơ chế an toàn Cài đặt hàm hủy tạo destructor Định nghĩa chồng toán tử gán Cung cấp hàm khởi tạo mặc định
HÀM HỦY TẠO (DESTRUCTOR) Tại sao cần hàm hủy tạo?
for (int i = 0; i < 1000000; i++){
Stack small;small.push(some_data);
}
some_datatop_node
some_data
some_data
some_data
some_data
HÀM HỦY TẠO (DESTRUCTOR)Stack::~Stack(){
while (!empty())pop(); // hủy Node
}
TOÁN TỬ GÁN(ASSIGNMENT OPERATOR)Stack outer_stack;for (int i = 0; i < 1000000; i++){
Stack inner_stack;inner_stack.push(some_data);inner_stack = outer_stack;
}
outer_stack.top_node
some_data
inner_stack.top_node
some_data
some_data
TOÁN TỬ GÁN(ASSIGNMENT OPERATOR)void Stack::operator=(const Stack &original){
Node *new_top;Node *new_copy;Node *original_node = original.top_node;if (original_node == NULL)
new_top = NULL;else{
new_top = new Node(original_node->entry);while (original_node->next != NULL){
original_node = original_node->next;new_copy->next = new Node(original_node->entry);
new_copy = new_copy->next;}
}}
TOÁN TỬ GÁN(ASSIGNMENT OPERATOR)
original_node
new_top
new_copy
original_top
top_nodetop_node
HÀM KHỞI TẠO SAO CHÉP(COPY CONSTRUCTOR) Hàm khởi tạo mặc định Hàm khởi tạo sao chép Tại sao phải dùng hàm khởi tạo sao chép?
void destroy_the_stack(Stack copy){}int main(){
Stack vital_data;destroy_the_stack(vital_data);
}
out_top
in_top
HÀM KHỞI TẠO SAO CHÉP(COPY CONSTRUCTOR)template <class Node_Entry>Stack<Node_Entry>::Stack(const Stack<Node_Entry> ©){
Node<Node_Entry> *new_copy;Node<Node_Entry> *original_node = original.top_node;if (original_node == NULL)
top_node = NULL;else{
new_copy = new Node<Node_Entry>(original_node->entry);top_node = new_copy;while (original_node = original_node->next != NULL){
original_node = original_node->next;new_copy->next = new Node<Node_Entry>(original->entry);new_copy = new_copy->next;
}}
}
HÀM KHỞI TẠO SAO CHÉP(COPY CONSTRUCTOR)
original_node
top_node
new_copy
original_top
ỨNG DỤNG THỰC TIỄN
T T TT T CPUT
Giả lặp xử lý song song: cơ chế Round Robin
ỨNG DỤNG THỰC TIỄN
BEGIN...CALL A...
RETURNEND
MAIN
MAIN
BEGIN...CALL B...
RETURNEND
SUB A
SUB A
BEGIN....RETURNEND
SUB B
ỨNG DỤNG THỰC TiỄN
TỔNG KẾT Ứng dụng đa dạng Hàng đợi: công việc có kể thứ tự trước
sau Ngăn xếp: công việc có tính chất quay
lui
THAM KHẢO Tìm kiếm chiều rộng Tìm kiếm chiều sâu Gọi chương trình con Cú pháp hậu tố Lỗi cài toán tử gán Danh sách liên kết vòng Danh sách liên kết kép
ỨNG DỤNG THỰC TIỄN
10 3
5
2 7 12
8 5
510
3
2
10 3 2 7 1
2
712
Tìm kiếm theo chiều rộng
ỨNG DỤNG THỰC TIỄN
10 3
5
2 7 12
8 5
5102
7
10 32 7 1
2
312
Tìm kiếm theo chiều rộng
ỨNG DỤNG THỰC TIỄN
2 * 4 - (9 + 5) (= -6)2 * 4 - 9 + 5 (= 4)
2 4 * 9 5 + -
8
2
44
2
8
9
5
5
9
1414
-6
Cú pháp hậu tố Ban Lan
HÀM HỦY TẠO (DESTRUCTOR) Tại sao cần hàm hủy tạo? Xét ví dụ:
for (int i = 0; i < 1000000; i++){
Stack small;small.push(some_data);
}
some_datatop_node
some_data
some_data
some_data
some_data
HÀM KHỞI TẠO SAO CHÉP(COPY CONSTRUCTOR)
top_node
original_top
x x
LIÊN KẾT KÉP, LIÊN KẾT VÒNG
min max
List