Khai triển stack sử dụng cấu trúc Khai triển: stack được thể hiện là 1 cấu trúc có 2 trường 1 để lưu trữ, 1 để theo dõi vị trí của phần tử trên cùng.. 1 stack sử dụng linked list là 1
Trang 1Chủ đề week 4 đề week 4
Trang 2 Stack là 1 cấu trúc dữ liệu tuyến tính mà chỉ có thể truy nhập tới phần tử cuối cùng của nó để nhập và xuất dữ liệu
Cấu trúc LIFO(Last in first out – vào sau ra
trước)
Trang 3Các phép toán trên Stack
• Initialize(stack) - khởi tạo
stack
• Pop(stack) - lấy ra phần tử trên đỉnh stack
Vậy làm thế nào để triển khai 1 stack?
Trang 4Phân tách khai triển từ đặc tả
Trang 6Đặc tả Stach (stack.h)
• typedef int Eltype;//kiểu phần tử mảng là int
StackType là mảng Max phần tử có kiểu Eltype
• int top;
• void Initialize(StackType stack);
• int full(StackType stack);
Trang 7Khai triển mảng của Stack (stack.c)
Trang 8Khai triển stack sử dụng cấu trúc
Khai triển: stack được thể hiện là 1 cấu trúc có 2 trường
1 để lưu trữ, 1 để theo dõi vị trí của phần tử trên cùng.
#define Max 50
typedef int Eltype;
typedef struct StackRec {
Trang 9Khai triển stack sử dụng cấu trúc
(*stack).storage[ (*stack).top]; }
Trang 10Khai triển sử dụng linked list
Khai triển stack sử dụng linked list rất đơn giản
1 stack sử dụng linked list là 1 và phép toán của linked list không sử dụng được cho stack
Là stack thì ta chỉ có 1 phép toán chèn(insert) duy nhất là push()
phép chèn vào trước
- Phép toán này giống như là phép xoá từ phía
trước
Trang 11Diễn tả bằng hình ảnh của stack
struct node {
int data;
struct node *link;
};
Trang 12 struct node *push(struct node *p, int value)
{
struct node *temp;
temp= (struct node *)malloc(sizeof(struct node)); if(temp==NULL) {
Trang 13Pop (linked list)
struct node *pop(struct node *p, int
Trang 14Sử dụng stack trong chương trình
scanf("%d",&n);
while( n == 1) {
top = pop(top,&value);
printf(“giá trị được pop ra là:
%d\n",value);
printf(" nhập 1 để pop 1 phần tử\n");
scanf("%d",&n);
} printf(" nhập 1 để tiếp tục\n "); scanf("%d",&n);
} while(n == 1);
}
Trang 15chương trình mà nhận từ người sử dụng 1 xâu,
và đảo ngược nó
Trang 16Cộng những số cực lớn
những số tương ững với các chữ số này trong 2 stacks.Sau đó thực hiện phép cộng bằng cách lấy các số (pop()) trong stack ra
Trang 17Cộng những số cực lớn
Thuật toán chi tiết
Đọc các chữ số của số đầu tiên và trữ các số tương ứng của chúng vào stack.
Đọc các chữ số của số thứ 2 và trữ các số tương ứng của chúng vào stack khác
result=0;
Trong khi còn ít nhất 1 Stack không rỗng:
- Pop 1 số từ mỗi stack không rỗng ra và cộng chúng.
- Push tổng (trừ đi 10 nếu cần thiết) vào stack kết quả
- Trữ số nhớ ở trong result.
Push số nhớ vào stack kết quả nếu nó khác 0.
Pop các số từ stack kết quả ra và trình diễn chúng ra màn hình.
Trang 18Exercise 4.1: Stack sử dụng mảng
thoại
"name", "telephone number" and "e-mail
address”
book từ 1 file vào 1 file khác sử dụng stack Đầu tiên đọc dữ liệu của 1 address book rồi push vào
1 stack.Rồi pop dữ liệu từ stack ghi ra 1 file khác theo thứ tự mà bạn pop ra.(tức là theo thứ tự
ngược với thứ tự đầu)
Trang 19Sự chuyển đổi sang kí pháp Balan ngược
sử dụng stack
pháp giữa sang biểu thức theo ký pháp Balan
ngược(bthức hậu tố).1 biểu thức bao gồm các chữ số dương (1->9) và 4 phép toán (+ - * /)
Đọc 1 biểu thức theo ký pháp giữa từ 1 đầu vào chuẩn, chuyển sang ký pháp Balan ngược và
đưa ra dưới dạng đầu ra chuẩn.Tham khảo sách giao khoa để có thêm chi tiết về ký pháp Balan ngược
Ví dụ:
Trang 20d.u.val = d1.u.val + d2.u.val; break;
d = pop(&eval);
return d.u.val;
}
Trang 211để lấy ra fần tử
(rear) và lấy ra (dequeue) ở đầu hàng (front)
Trang 22Cấu trúc dữ liệu FIFO
tự mà chúng được thêm vào
Trang 23Phép toán trên queue
Tạo 1 hàng đợi rỗng trong có kich thước lớn nhất
là max_queue_size
if(nếu số fần tử trong hàng đợi
==max_queue_size)
return TRUE
else return FALSE
Trang 24Phép toán trên queue
Queue EnQ(queue, item) ::=
if (IsFullQ(queue)) hàng đợi đã đầy không chèn thêm được else thêm 1 fần tử vào cuối hàng đợi và return queue;
Boolean IsEmptyQ(queue) ::=//ktra queuecos rỗng k?
Trang 25Khai triển sử dụng mảng và cấu trúc
Trang 26Khởi tạo và kiểm tra trạng thái
Trang 27void EnQueue(ElementType X,Queue *Q){
if (!Full_Queue(*Q)){
if (Empty_Queue(*Q)) Q->Front=0;Q->Rear=Q->Rear+1;
Q->Element[Q->Rear]=X;
}
else printf("Queue is full!");
}
Trang 28else printf("Queue rỗng!");
}
Trang 29Khai triển 2: Coi 1 mảng là 1 hàng đợi
vòng
fần tử đầu tiên
Rear(cuối): vị trí cuối hiện tại
hiểu rõ hơn.)
Vấn đề: còn lại 1 vị trí trống khi queue đầy
Trang 30Queue đã đầy chưa?
int Full_Queue(Queue Q){
return (Q.Rear-Q.Front+1) %
MaxLength==0;//fép chia lấy số dư}
Trang 32} else printf("Queue is full!");
}
Trang 33Khai triển sử dụng List
triển các fép toán trên hàng đợi bằng cách sử
dụng lại các fép toán đã khai triển trên list
Trang 34Khai triển sử dụng 1 list
Trang 35Khởi tạo 1 hàng đợi rỗng
void MakeNullQueue(Queue *Q){
Position Header;
Header=(Node*)malloc(sizeof(Node));//cấp fát bộ nhớ cho Header
Header->Next=NULL;
Q->Front=Header;
Q->Rear=Header;
}
Trang 36int EmptyQueue(Queue Q){return (Q.Front==Q.Rear);}
Trang 38else printf(”Error: queue rỗng.”);}
Trang 39Exercise 4-3:Hàng đợi sử dụng list
thoại
"name", "telephone number" and "e-mail
address”
book từ 1 file vào 1 file khác sử dụng queue Đầu tiên đọc dữ liệu của 1 address book rồi
thêm vào queue.Rồi lấy dữ liệu từ queue ghi ra
1 file khác theo thứ tự mà bạn lấy ra.(tức là
theo đúng với thứ tự đầu)
Trang 40hàng đợi được ấn định là 10
dấu cách từ 1 đầu vào chuẩn, và đẩy chúng vào hàng đợi.Khi chương trình đọc 11 số nguyên,
hàng đợi đã đầy rồi Chương trình fải loại bỏ số nguyên đầu tiên và thêm số nguyên thứ 11
vào.In số nguyên bị loại bỏ theo 1 đầu ra chuẩn
này
Trang 41Boolean IsEmpty(queue) ::= front == rear
Boolean IsFullQ(queue) ::= rear ==
MAX_QUEUE_SIZE-1
Trang 43return queue [++ *front];
}
Trang 44void addq(int front, int *rear, element item)
{
*rear = (*rear +1) % MAX_QUEUE_SIZE;
if (front == *rear) /* thiết lập lại đuôi hàng đợi và
Trang 45/* hàng đợi rỗng, trả về giá trị là bị lỗi*/
*front = (*front+1) % MAX_QUEUE_SIZE;return queue[*front];
}