1. 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
2. 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
3. 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
4. 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
5. 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)
6. 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
8. CÀI ĐẶT NGĂN XẾP BẰNG
DANH SÁCH ĐẶC (Stack.h)
const max_stack = 100; // kích thước tối đa
template <class Stack_Element>
// Stack_Element=int, double, string, Employee
class Stack
{
private: // định nghĩa cấu trúc dữ liệu
int 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ượng
Stack(); // hàm khởi tạo mặc định
bool empty() const;
bool full() const;
bool push(const Stack_Entry &item);
bool pop();
};
count
12. CÀI ĐẶT NGĂN XẾP BẰNG
DANH SÁCH LIÊN KẾT
template <class Node_Entry>
struct Node
{
Node_Entry entry;
Node<Node_Entry> *next;
Node(); // hàm khởi tạo mặc định
Node(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;
}
entry
next
item entry
13. CÀI ĐẶT NGĂN XẾP BẰNG
DANH SÁCH LIÊN KẾT
template <class Node_Entry>
class Stack
{
private:
Node<Node_Entry> *top_node;
public:
Stack(); // hàm khởi tạo mặc định
bool empty() const;
//bool full() const;
bool push(const Node_Entry &item);
bool pop();
};
entry
14. CÀI ĐẶT NGĂN XẾP BẰNG
DANH SÁCH LIÊN KẾT
template <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
15. CÀI ĐẶT NGĂN XẾP BẰNG
DANH SÁCH LIÊN KẾT
template <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
16. CÀI ĐẶT NGĂN XẾP BẰNG
DANH SÁCH LIÊN KẾT
template <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_node
delete old_top;
return true;
}
entry entry entryentry
17. 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
18. CÀI ĐẶT HÀNG ĐỢI BẰNG
DANH SÁCH ĐẶC
Hàng đợi rỗng
Hàng đợi đầy
front rear front
frontrear rear
19. CÀI ĐẶT HÀNG ĐỢI BẰNG
DANH SÁCH ĐẶC
const max_queue = 100;
template <class Entry_Element>
class Queue
{
private:
int count; // số phần tử
int front; // vị trí đầu hàng đợi
int rear; // vị trị cuối hàng đợi
Entry_Element entry[max_queue];
public:
Queue(); // hàm khởi tạo mặc định
bool empty() const;
bool full() const;
bool serve(); // dequeue
bool append(const Queue_Entry &item); // enqueue
};
item item item item
count = 4
front
rear
20. CÀI ĐẶT HÀNG ĐỢI BẰNG
DANH SÁCH ĐẶC
template <class Queue_Element>
Queue<Queue_Element>::Queue()
{
count = 0;
front = 0;
rear = max_queue - 1;
}
front rear
21. CÀI ĐẶT HÀNG ĐỢI BẰNG
DANH SÁCH ĐẶC
template <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
22. CÀI ĐẶT HÀNG ĐỢI BẰNG
DANH SÁCH ĐẶC
template <class Queue_Element>
bool Queue<Queue_Element>::append(const Queue_Element &item)
{
if (full()) // queue đầy
return 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
23. CÀI ĐẶT HÀNG ĐỢI BẰNG
DANH SÁCH ĐẶC
template <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
24. CÀI ĐẶT HÀNG ĐỢI BẰNG
DANH SÁCH LIÊN KẾT
template <class Node_Entry>
class Queue
{
private:
Node<Node_Entry> *front;
Node<Node_Entry> *rear;
public:
Queue(); // hàm khởi tạo mặc định
bool empty() const;
//bool full() const;
bool append(const Node_Entry &item);
bool serve();
};
Node_Entry
front rear
25. CÀI ĐẶT HÀNG ĐỢI BẰNG
DANH SÁCH LIÊN KẾT
template <class Node_Entry>
Queue<Node_Entry>::Queue()
{
front = NULL;
rear = NULL;
}
template <class Node_Entry>
bool Queue<Node_Entry>::empty()
{
return (front == NULL);
}
26. 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
27. CÀI ĐẶT HÀNG ĐỢI BẰNG
DANH SÁCH LIÊN KẾT
template <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
28. 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
29. 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
30. 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_data
top_node
some_data
some_data
some_data
some_data
31. HÀM HỦY TẠO (DESTRUCTOR)
Stack::~Stack()
{
while (!empty())
pop(); // hủy Node
}
32. 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
35. 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
41. 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
42. 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
43. ỨNG DỤNG THỰC TIỄN
10 3
5
2 7 12
8 5
5
10
3
2
10 3 2 7 12
7
12
Tìm kiếm theo chiều rộng
44. ỨNG DỤNG THỰC TIỄN
10 3
5
2 7 12
8
5
5
10
2
7
10 32 7 12
3
12
Tìm kiếm theo chiều rộng
45. Ứ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
46. 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_data
top_node
some_data
some_data
some_data
some_data
47. HÀM KHỞI TẠO SAO CHÉP
(COPY CONSTRUCTOR)
top_node
original_top
x x