Nói cách khác, ngăn xếp là một cấu trúc dữ liệu có 2 thao tác cơ bản: bổ sung push và loại bỏ pop, trong đó loại bỏ sẽ tiến hành loại phần tử mới nhất được đưa vào danh sách.. Chính vì t
Trang 1Đề tài: Ứng dụng của Stack- Ngăn xếp
Phần I: Giới thiệu về ngăn xếp
1 Khái niệm
Ngăn xếp là một dạng đặc biệt của danh sách mà việc bổ sung hay loại bỏ một phần
tử đều được thực hiện ở một đầu của danh sách gọi là đỉnh Nói cách khác, ngăn xếp là một cấu trúc dữ liệu có 2 thao tác cơ bản: bổ sung (push) và loại bỏ (pop), trong đó loại
bỏ sẽ tiến hành loại phần tử mới nhất được đưa vào danh sách Chính vì tính chất này mà ngăn xếp còn được gọi kiểu dữ liệu có nguyên tắc LIFO (Last in first out – vào sau ra trước)
2 Các tác vụ trên ngăn xếp
a) Initialize
Chức năng: Khởi động ngăn xếp
Dữ liệu nhập: Không
Dữ liệu xuất: stack top về vị trí khởi đầu
b) Empty
Chức năng kiểm tra ngăn xếp có bị rỗng không
Dữ liệu nhập: Không
Dữ liệu xuất: True or False (True: khi ngăn xếp rỗng, False: ngăn xếp không bị rỗng)
c) Pusth
Chức năng: thêm nút mới tại đỉnh ngăn xếp
Dữ liệu nhập: nút mới
Dữ liệu xuất: không
d) Pop
Chức năng: xóa nút tại đỉnh ngăn xếp
Dữ liệu nhập: Không
Điều kiện: stack không bị rỗng
Trang 2Dữ liệu xuất: nút bị xóa.
e) Stacktop:
Chức năng: truy xuất nút tại đỉnh ngăn xếp
Dữ liệu nhập: Không
Điều kiện: stack không bị rỗng
Dữ liệu xuất: nút tại đỉnh ngăn xếp
f) Stacksize
Chức năng: xác định số nút hiện có trong ngăn xếp
Dữ liệu: Không
Dữ liệu xuất: số nút hiện có trong ngăn xếp
g) Clearstack
Chức năng: xóa tất cả các nút ở trong ngăn xếp
Dữ liệu nhập: không
Dữ liệu xuất:stack top về vị trí khởi đầu
h) Copystack:
Chức năng: copy ngăn xếp thành ngăn xếp mới
Dữ liệu nhập: stack nguồn
Dữ liệu xuất: ngăn xếp mới giống ngăn xếp cũ
3 Phương pháp cài đặt ngăn xếp
Có rất nhiều cách cài đặt một ngăn xếp nhưng đơn giản cũng như để dễ hình dung nhất
là cài đặt bằng mảng hay còn gọi là cài đặt theo kiểu kế tiếp Ngoài ra còn nhiều cách cài đặt khác như cài đặt bằng Danh sách liên kết (DSLK đơn, DSLK vòng, DSLK kép, DSLK vòng+kép)
Trang 3Phần II: Ứng dụng ngăn xếp vào bài toán cụ thể- Bài toán sửa kho tàu
1 Mô tả bài toán
Xét mạng đường sắt sau đây:
Các toa tàu ở đường ray A bên phải (được đánh số 1, 2, , n) cần phải hoán vị chuyển sang đường ray B bên trái B được xem như đầu ra của các toa tàu, còn A được xem là đầu vào Một toa có thể chuyển thẳng sang đường ray bên trái, hay nó có thể rẽ xuống đường ray bên cạnh (để sửa chữa) để sau này sẽ đi ra đường ray bên trái Các toa tàu không được phép đi ngược chiều
Cho trước một hoán vị toa tàu ở đầu ra B Hãy cho biết liệu hoán vị đó có xảy ra hay không
Ví dụ: Ở đầu vào, có 4 toa tàu, ở đầu ra các toa tàu theo thứ tự là 3, 1, 4, 2 Hoán vị
này không thể xảy ra Vì toa đầu tiên là toa 3, điều này chứng tỏ nó đi thẳng ra đầu ra B, còn các toa 1 và 2 được chuyển vào kho Khi ra khỏi kho thì toa 2 phải ra trước nghĩa là phải có thứ tự 2 trước 1 Điều này mâu thuẫn với thứ tự 2 sau 1 trong hoán vị 3, 1, 4, 2
2 Ý tưởng của bài toán
Bài toán cần kiểm tra tính hợp lệ của hoán vị toa tàu ở đường ray ra, dãy các toa ở đường ray vào mặc định là dãy 1, 2, , n theo thứ tự từ trái qua phải.
- Gọi (b) = {b 1 , b 2 , , b n } là dãy toa tàu ở đường ray vào, thì b i = i với i = 1, 2, ,n.
- Gọi (a) = {a 1 , a 2 , , a n } là dãy các toa tàu ở đường ray ra Việc kiểm tra tính hợp
lệ của dãy (a) như sau:
Lần lượt xét các toa tàu a i ở đường ray ra theo chiều từ trái sang phải, nghĩa là ităng dần từ 1, 2, , đến n
- Với mỗi toa a i ta tìm xem nó có trong đường ray vào không.
- Nếu a i có trong (b) thì mọi toa tàu d có có chỉ số nhỏ hơn a i chắc chắn đã được đưa vào kho sửa chữa, ví dụ với n = 5, nếu a1 = 4 thì chắc chắn các toa 1, 2, 3 đã được
đưa vào kho sửa chữa Khi đó ta đưa tất cả các toa d này vào kho (tức là đẩy chúng vào một ngăn xếp), trước khi xét toa tầu tiếp theo ở đường rayra
- Nếu a i không có trong (b) thì chắc chắn nó phải ở trong kho, hơn nữa phải ở vị trí cửa kho sửa chữa (đỉnh ngăn xếp) Nếu a i có ở vị trí cửa kho thì ta “lấy nó ra” khỏi kho, nếu
Trang 4ngược lại thì chứng tỏ dãy (a) là dãy hoán vị không hợp lệ tại i, và đây là dấu hiệu duy nhất để kiểm tra một dãy (a) có hợp lệ hay không
3 Thuật toán
Bước 1: nhập số toa tàu, nhập hoán vị đầu ra cho trước b[i], đầu vào a[i] đánh STT 1…n
Bước 2: Nếu stack có phần tử thì so sánh với phần tử của mảng b đang xét
2.1 i=1
2.2 Nếu phần tử x ở đỉnh của stack = b[i] đang xét: chuyển 2.3, ngược lại tới 2.7
2.3 c[i]=b[i]
2.4 in ra toa này được chuyển từ kho ra đường ray ra C
2.5 tăng i thêm 1;
2.6 kiểm tra ngăn xếp Nếu ngăn xếp rỗng chuyển bước 3, ngược lại chuyển bước 2.2 2.7 Dừng lại
Bước 3: Nếu stack k có phần tử thì lần lượt kiểm tra các phần tử trong mảng đầu vào 3.1 j=1
3.2 Nếu a[j] = b[i], tới 3.3, ngược lại tới 3.7
3.3 c[i] = b[i];
3.4 In cách dịch chuyển toa này: từ đường ray vào A đến đường ray ra C
3.5 Tăng j : j++
3.6 Kiểm tra j<n, nếu đúng tới bước 3.2, ngược lại tới bước 4
3.7 Đưa a[j] vào stack
3.8 In cách dịch chuyển toa này: từ đường ray vào A đến đường ray D
Bước 4: Sau khi duyệt hết các phần tử trong b mà ngăn xếp vẫn còn phần tử, in ra không chuyển được nữa, hoán vị không xảy ra, ngược lại nếu ngăn xếp rỗng tới bước 5 Bước 5: In ra: hoán vị có thể xảy ra
Trang 54 Sơ đồ khối
Trang 65 Chương trình
Sử dụng phần mềm Cfree để chạy chương trình (chương trình được lưu bằng file CPP đính kèm)
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#define MAX 1000
#define TRUE 1
#define FALSE 0
int n;
int j, found;
int P[MAX], B[MAX];
int *b;
// Cai dat stack bang mang
typedef struct {
int top;
int d[MAX];
}stack;
// Khoi tao stack
void stackInitialize( stack *s)
Trang 7s->top = - 1;
return;
}
// Kiem tra ngan xep rong
int stackEmpty( stack *s)
{
if(s->top == -1) return 1;
return 0;
}
// Them phan tu vao ngan xep
int push(stack *s, int x) {
s->top = (s->top) + 1;
s->d[s->top] = x;
return s->d[s->top];
}
// Lay 1 phan tu ra khoi ngan xep
int pop(stack *s) {
return(s->d[s->top ]);
}
Trang 8// Ham kiem tra hoan vi co xay ra hay khong
void KiemTra() {
stack s;
s.top = -1;
int *a, *c;
int i, j, count, found, x;
count = 1; found = 0;
a = (int*)malloc((n+1)*sizeof(int));
c = (int*)malloc((n+1)*sizeof(int));
printf("\n Ta chuyen lan luot roi dua ra thong bao hoan vi co xay ra hay khong.\
n ");
for(i = 1; i <= n; i++)
a[i] = i;
for(i = 1; i <= n; i++) {
while(!stackEmpty(&s)) {
x = s.d[s.top];
if(x == b[i]) {
c[i] = b[i];
printf(" chuyen tu D sang C");
pop(&s);
i++;
}
else break;
}
Trang 9for(j = count; j <= n; j++) {
if(a[j] == b[i]) {
c[i] = b[i];
printf(" chuyen tu A sang C");
count ++;
break;
}
else {
push(&s, a[j]);
printf(" chuyen tu A sang D");
count ++;
}
}
}
if ( (count > n) &&(!stackEmpty(&s)) ) {
printf(" Hoan vi khong xay ra!");
}
if ( (count > n) &&(stackEmpty(&s)) ) printf(" Hoan vi co xay ra!"); free(a); free(c);
getch();
Trang 10/// Ham kiem tra phuc vu cho viec liet ke cac hoan vi co the xay ra void KiemTraHoanVi() {
stack s;
s.top = -1;
int *a, *c;
int i, j, count, x;
count = 1; found = 0;
a = (int*)malloc((n+1)*sizeof(int));
c = (int*)malloc((n+1)*sizeof(int));
for(i = 1; i <= n; i++)
a[i] = i;
for(i = 1; i <= n; i++) {
while(!stackEmpty(&s)) {
x = s.d[s.top];
if(x == b[i]) {
c[i] = b[i];
pop(&s);
i++;
}
else break;
}
Trang 11for(j = count; j <= n; j++) {
if(a[j] == b[i]) {
c[i] = b[i];
count ++;
break;
}
else {
push(&s, a[j]);
count ++;
}
}
}
if ( (count > n) &&(!stackEmpty(&s)) ) {
found = FALSE;
}
if ( (count > n) &&(stackEmpty(&s)) ) found = TRUE; free(a); free(c);
}
/// Dua ra cac hoan vi
void result() {
int i;
b = (int*)malloc((n+1)*sizeof(int));
for(i = 1; i <= n; i++)
b[i] = P[i];
Trang 12KiemTraHoanVi();
if(found == TRUE) {
for(i = 1; i <= n; i++) printf("%3d", b[i]); printf("\n");
}
free(b);
}
/// Ham phuc vu sinh hoan vi
void Try(int i) {
int j;
for(j = 1; j <= n; j++) {
if(B[j]) {
P[i] = j;
B[j] = FALSE;
if(i == n) result();
else Try(i + 1);
B[j] = TRUE;
}
}
}
void Cackhanang(){
Trang 13
for(int i = 1; i <= n; i++) B[i] = TRUE;
Try(1);
getch();
}
main() {
int ch;
printf("\n So toa tau n = ");
scanf("%d", &n);
printf("\nChon 1 trong 3 chuc nang: \n");
printf("\nChon phim 1 neu muon kiem tra 1 hoan vi la co xay ra hay ko"); printf("\nChon phim 2 neu muon dua ra tat ca hoan vi co the xay ra."); printf("\nChon phim 3 de thoat khoi chuong trinh.\n");
while(1) {
printf("\nChon chuc nang: "); scanf("%d", &ch);
// <ul>
switch(ch) {
case 1:
b = (int*)malloc((n+1)*sizeof(int));
printf("\n Nhap thu tu can tao: \n");
fflush(stdin);
for(int i = 1; i <= n; i++) {
printf("\n b[%d] = ", i);
Trang 14scanf("%d", &b[i]);
}
KiemTra();
free(b);break;
case 2:
printf("\n Cac hoan vi co the tao thanh la: \n");
Cackhanang();break;
case 3:
exit(0);
default:
printf("\n Chuc nang ban chon ko co Xin chon lai"); getch();
}
}
}
Trang 156 Demo chương trình