1. Trang chủ
  2. » Công Nghệ Thông Tin

Tài liệu Giáo trình cấu trúc dữ liệu và giải thuật_Chương 3: Cấu trúc Stack & Queue pptx

18 791 3

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Cấu trúc Stack & Queue
Trường học Trường Đại Học Công Nghệ Thông Tin
Chuyên ngành Cấu trúc dữ liệu và giải thuật
Thể loại Giáo trình
Định dạng
Số trang 18
Dung lượng 178,5 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

GIỚI THIỆU VỀ STACK 1.1 Khái niệm về stack Stack có thể được xem là một dạng danh sách đặc biệt trong đó các tác vụ thêm vào hoặc xóa đi một phần tử chỉ diễn ra ở một đầu gọi là đỉnh sta

Trang 1

Chương 3

CẤU TRÚC STACK & QUEUE

1 GIỚI THIỆU VỀ STACK

1.1 Khái niệm về stack

Stack có thể được xem là một dạng danh sách đặc biệt trong đó các tác vụ thêm vào hoặc xóa đi một phần tử chỉ diễn ra ở một đầu gọi là đỉnh stack Trên stack các nút được thêm vào sau lại được lấy ra trước nên cấu trúc stack còn được gọi là LIFO (Last In First Out)

Stack được dùng rộng rải để giải quyết các vấn đề có cơ chế LIFO, ví dụ các trình biên dịch của các ngôn ngữ lập trình thường dùng stack để kiểm tra cú pháp của các câu lệnh, để xử lý các biểu thức toán học, để xử lý việc gọi các chương trình con, xử lý việc gọi hàm đệ qui … Stack cũng thường được dùng để chuyển một giải thuật đệ qui thành giải thuật không đệ qui

Có hai tác vụ chính trên stack là tác vụ push dùng để thêm một phần tử vào đỉnh stack và tác vụ pop dùng để xoá đi một phần tử ra khỏi đỉnh stack

Hình sau đây mô tả hình ảnh của stack qua các tác vụ:

push(s,A): hình a

push(s,B): hình b

pop(s): hình c

push(s,C): hình d

1.2 Mô tả stack

Mô tả dữ liệu:

Stack là một kiểu dữ liệu trừu tượng có nhiều nút cùng kiểu dữ liệu trải dài từ đáy stack đến đỉnh stack

Mô tả các tác vụ:

 Tác vụ initialize:

Chức năng: khởi động stack

Dữ liệu nhập: không

Dữ liệu xuất: stack top trở về đầu stack

 Tác vụ empty

Chức năng: kiểm tra stack có rỗng hay không

Dữ liệu nhập: không

Dữ liệu xuất: TRUE|FALSE

Trang 2

 Tác vụ push

Chức năng: thêm nút mới tại đỉnh stack

Dữ liệu nhập: nút mới

Dữ liệu xuất: không

 Tác vụ pop

Chức năng: xóa nút tại đỉnh stack

Dữ liệu nhập: không

Điều kiện: stack không bị rỗng

Dữ liệu xuất: nút bị xoá

 Tác vụ stacktop

Chức năng: truy cập nút tại đỉnh stack

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 stack

 Tác vụ stacksize

Chức năng: xác định số nút hiện có trong stack

Dữ liệu nhập: không

Dữ liệu xuất: số nút hiện có trong stack

 Tác vụ clearstack

Chức năng: xoá tấc cả các nút có trong stack

Dữ liệu nhập: không

Dữ liệu xuất: stack top về vị trí khởi đầu

1.3 Ứng dụng của stack

 Stack thường được dùng để giải quyết các vấn đề có cơ chế LIFO

 Stack thường được dùng để giải quyết các vấn đề trong trình biên dịch của các ngôn ngữ lập trình như:

 kiểm tra cú pháp của các câu lệnh trong ngôn ngữ lập trình

 Xử lý các biểu thức toán học: kiểm tra tính hợp lệ của các dấu trong ngoặc một biểu thức, chuyển biếu thức từ dạng trung tố (infix) sang dạng hậu tố (postfix), tính giá trị của biểu thứ dạng hậu tố

 Xử lý việc gọi các chương trình con

 Stack thường được sử dụng để chuyển một giải thuật đệ qui thành giải thuật không đệ qui

2 HIỆN THỰC STACK

2.1 Hiện thực stack bằng danh sách kề

Khai báo cấu trúc stack: là môt mẩu tin có hai trường:

 Trường top: là một số nguyên chỉ đỉnh stack

 Trường nodes: là mảng một chiều, mỗi phần tử của mảng là một nút của stack

#define MAXSTACK 100

struct stack{

int top;

int nodes[MAXSTACK];

}

Trang 3

Tác vụ empty

int empty(struct stack *ps){

if(ps->top==-1)

return TRUE;

else

return FALSE;

}

Tác vụ push

void push(struct stack *ps, int x){

ps->nodes[++(ps->top)]=x;

}

Tác vụ pop

int pop(struct stack *ps){

if(empty(ps)){

printf(“Stack bi rong”);

}else{

return ps->nodes[ps->top ];

}

}

2.2 Hiện thực stack bằng danh sách liên kết

Khai báo cấu trúc stack:

struct node{

char info;

node *next;

};

typedef struct node* NODEPTR;

NODEPTR top;

Tác vụ khởi tạo stack

void initialize(){

top=NULL;

}

Tác vụ kiểm tra stack rỗng

int empty(){

if (top==NULL)

return TRUE;

else

}

Tác vụ cấp phát bộ nhớ

NODEPTR getnode(char c){

Trang 4

NODEPTR q;

q=(NODEPTR)malloc(sizeof(struct node));

q->info=c;

q->next=NULL;

return q;

}

Tác vụ thêm một phần tử vào stack

void push(char c){

NODEPTR p;

p=getnode(c);

p->next=top;

top=p;

}

Tác vụ lấy một phần tử ra khỏi stack

char pop(){

NODEPTR p;

char c;

f(top !=NULL){

p=top;

top=top->next;

c=p->info;

free(p);

return c;

}else{

printf("\n stack trong");

return -1;

}

}

3 CÁC CHƯƠNG TRÌNH MINH HOẠ

3.1 Chương trình đảo chuỗi dùng stack

#include <stdio.h>

#include <stdlib.h>

#include <conio.h>

#include <string.h>

#define MAXSTACK 100

#define TRUE 1

#define FALSE 0

//dinh nghia stack

struct stack{

int top;

char nodes[MAXSTACK];

};

Trang 5

//empty operation: check for whether stack is empty

int empty(struct stack *ps){

if(ps->top==-1){

return TRUE;

}

else{

return FALSE;

}

}

// dua 1 ky tu vao stack

void push(struct stack* ps, char x){

if(ps->top==MAXSTACK-1)

printf("%s","Stack is full");

else{

ps->top+=1;

ps->nodes[ps->top]=x;

}

}

//lay mot ky tu ra khoi stack

char pop(struct stack *ps){

if(empty(ps))

printf("%s","Stack bi rong");

else{

char c;

c=ps->nodes[ps->top];

ps->top-=1;

return c;

}

return ' ';

}

void main()

{

struct stack s;

char c, chuoi[MAXSTACK];

int i, vitri;

clrscr();

do{

s.top=-1;

printf("\n\n Chuoi ban nhap vao:");

scanf("%s",chuoi);

vitri =strlen(chuoi);

for(i=0; i<vitri;i++){

push(&s,chuoi[i]);

} printf("\n\n Chuoi dao la: ");

while(!empty(&s)){

Trang 6

printf("%c",pop(&s));

} printf("\n\n Tiep tuc khong? (c/k): ");

c=getche();

}while(c=='c'||c=='C');

}

3.2 Chương trình đổi cơ số thập phân sang cơ số bất kỳ

#include <stdio.h>

#include <stdlib.h>

#include <conio.h>

#define MAXSTACK 100

#define TRUE 1

#define FALSE 0

typedef struct stack{

int top;

int nodes[MAXSTACK];

} STACK;

//Check stack is empty

int empty(STACK *ps){

if(ps->top==-1)

return TRUE;

else

}

//dua vao stack

void push(STACK *ps, int x){

if(ps->top==MAXSTACK -1)

printf("\n Stack bi day");

else{

ps->top++;

ps->nodes[ps->top]=x;

}

}

//lay ra khoi stack

int pop(STACK *ps){

if(empty(ps))

printf("\nStack bi rong");

else{

int i=ps->nodes[ps->top];

ps->top ;

return i;

}

return -1;

}

void main(){

Trang 7

STACK s;

int coso,so,sodu;

char c;

do{

s.top=-1;

printf("\n Nhap vao mot so thap phan");

scanf("%d",&so);

printf("\n Co so ban muon doi sang: ");

scanf("%d",&coso);

while( so !=0){

sodu=so %coso;

push(&s, sodu);

so=so/coso;

} printf("\n So da doi la: ");

while(!empty(&s)){

printf("%X",pop(&s));

} printf("\n \n Ban co muon tiep tuc khong? ");

c=getche();

}while(c=='c'||c=='C');

}

3.3 Chương trình đảo chuỗi hiện thực stack bằng danh sách liên kết

#include<stdlib.h>

#include<stdio.h>

#include <string.h>

#define TRUE 1

#define FALSE 0

struct node{

char info;

node *next;

};

typedef struct node* NODEPTR;

NODEPTR top;

void initialize(){

top=NULL;

}

int empty(){

if (top==NULL)

return TRUE;

else

}

NODEPTR getnode(char c){

NODEPTR q;

Trang 8

q=(NODEPTR)malloc(sizeof(struct node));

q->info=c;

q->next=NULL;

return q;

}

void push(char c){

NODEPTR p;

p=getnode(c);

p->next=top;

top=p;

}

char pop(){

NODEPTR p;

char c;

f(top !=NULL){

p=top;

top=top->next;

c=p->info;

free(p);

return c;

}else{

printf("\n stack trong");

return -1;

}

}

void main(){

char chuoi[30];

int chieudai,i;

initialize();

printf("\n Nhap vao chuoi: ");

scanf("%s",chuoi);

chieudai=strlen(chuoi);

for(i=0;i<chieudai;i++)

push(chuoi[i]);

printf("\n Chuoi dao: ");

while(!empty()){

printf("%c",pop());

}

}

4 GIỚI THIỆU VỀ QUEUE

Queue là một dạng danh sách đặt biệt, trong đó chúng ta chỉ được phép thêm vào các phần tử ở cuối hàng đợi và xoá đi các phần tử ở đầu hàng đợi Vì phần tử thêm vào trước được lấy ra trước nên cấu trúc hàng đợi còn được gọi là cấu trúc FIFO( First In First Out)

Trang 9

Hàng đợi là cấu trúc được sử dụng rộng rãi trong thực tế: người ta dùng hàng đợi để giải quyết các vấn đề có cấu trúc FIFO như xử lý các dịch vụ của ngân hàng, để xử lý các tiến trình đang đợi phục vụ trong các hệ điều hành nhiều người sử dụng, quản lý các yêu cầu

in trên máy print servers…

4.1 Khái niệm về hàng đợi

Hàng đợi chứa các nút có cùng kiểu dữ liệu trải dài từ đầu hàng đợi (front) đến cuối hàng đợi (rear)

Có hai tác vụ chính trên hàng đợi là insert – thêm nút mới vào cuối hàng đợi và tác vụ remove dùng để xoá một phần tử ra khỏi hàng đợi

Hình vẽ sau đây dùng để mô tả hàng đợi qua các tác vụ như sau:

 Trạng thái bắt đầu: hàng đợi bị rỗng (hình a)

 insert (q,A)

 insert (q,B)

 insert (q,C) (hình b)

 insert(q,D) (hình d)

 insert(q,E) (hình f)

Trang 10

4.2 Mô tả hàng đợi

Mô tả dữ liệu:

Hàng đợi là một kiểu dữ liệu trừu tượng có nhiều nút cùng kiểu dữ liệu trải dài từ đầu hàng đợi đến cuối hàng đợi

Mô tả các tác vụ:

 Tác vụ initialize

Chức năng: khởi động hàng đợi

Dữ liệu nhập: không

Dữ liệu xuất: hai con trỏ front và rear được gán các giá trị phù hợp

 Tác vụ empty

Chức năng: kiểm tra hàng đợi có bị rỗng hay không

Dữ liệu nhập: không

Dữ liệu xuất: TRUE|FALSE

 Tác vụ insert

Trang 11

Chức năng: Thêm nút mới vào hàng đợi.

Dữ liệu nhập: nút mới

Điều kiện: hàng đợi không bị đầy

Dữ liệu xuất: không

 Tác vụ remove

Chức năng: xóa nút tại đầu hàng đợi

Dữ liệu nhập: không

Điều kiện: hàng đợi không bị rỗng

Dữ liệu xuất: nút bị xóa

 Tác vụ queuefront

Chức năng: truy xuất nút tại đầu hàng đợi

Dữ liệu nhập: không

Điều kiện: hàng đợi không bị rỗng

Dữ liệu xuất: nút tại đầu hàng đợi

 Tác vụ queuerear

Chức năng: truy xuất nút cuối của hàng đợi

Dữ liệu nhập: không

Điều kiện: hàng đợi không bị rỗng

Dữ liệu xuất: nút cuối cùng của hàng đợi

 Tác vụ queuesize

Chức năng: xác định số nút hiện có trong hàng đợi

Dữ liệu nhập: không

Dữ liệu xuất: số nút có trong hàng đợi

 Tác vụ clearqueue

Chức năng: xoá tất cả các nút có trong hàng đợi

Dữ liệu nhập: Không

Dữ liệu xuất: front và rear được trả về vị trí ban đầu

4.3 Ứng dụng của hàng đợi

 Hàng đợi được dùng để giải quyết các vấn đề có cơ chế FIFO (First In First Out)

 Trong thực tế người ta thường cài đặt hàng đợi trong các chương trình xử lý các dịch vụ ngân hàng, xử lý các tác vụ đang đợi phục vụ trong các hệ điều hành đa người sử dụng, quản lý các yêu cầu in trong máy server printers…

5 HIỆN THỰC QUEUE

5.1 Dùng mảng vòng hiện thực hàng đợi

Đây là cách thường dùng nhất để cài đặt hàng đợi theo kiểu kế tiếp Lúc này ta xem mảng như là mảng vòng chứ không phải là mảng thẳng: nút nodes[0] xem như là nút sau của nút nodes[MAXQUEUE -1]

Khai báo cấu trúc:

#define MAXQUEUE 100

struct queue{

int front, rear;

int nodes[MAXQUEUE];

}

Trang 12

Tác vụ khởi động:

void initialize(struct queue *pq){

pq->front=pq->rear=MAXQUEUE-1;

}

Tác vụ kiểm tra hàng đợi trống:

int empty(struct queue *pq){

if(pq->front==pq->rear)

return TRUE;

else{

return FALSE;

}

}

Tác vụ thêm vào hàng đợi:

void insert(struct queue *pq, int x){

if(pq->rear==MAXQUEUE -1)

pq->rear=0;

else

pq->rear++;

if(pq->rear==pq->front)

printf(“Hang doi bi day”);

else

pq->nodes[pq->rear]=x;

}

Tác vụ xoá một phần tử ra khỏi hàng đợi

int remove(struct queue *pq){

if(empty(pq))

printf(“hang doi bi day”);

else{

if(pq->front==MAXQUEUE-1)

pq->front=0;

else

pq->front++;

return pq->nodes[pq->front];

}

}

Tác vụ duyệt hàng đợi

void traverse(struct queue *pq){

int i;

if(empty(pq)){

printf(“Hang doi bi rong”);

return;

}

Trang 13

i=0;

else

i=pq->front+1;

while(i!=pq->rear){

printf(“%d”,pq->nodes[i]);

if(i==MAXQUEUE-1)

i=0;

else

i++;

}

printf(“%d”,pq->nodes[i]);

}

5.2 Dùng danh sách liên kết hiện thực hàng đợi

Ta có thể cài đặt hàng đợi như một danh sách liên kết: con trỏ đầu danh sách liên kểt front chỉ nút tại đầu hàng đợi, con trỏ rear trỏ đến nút cuối cùng của hàng đợi

Hình vẽ sau thể hiện cách cài đặt hàng đợi bằng danh sách liên kết

Với cách cài đặt này ta có thể hiện thực các tác vụ của hàng đợi như: insert, remove, empty…trên danh sách liên kết

5.3 Hàng đợi có ưu tiên

Hàng đợi hoạt động trên nguyên tắc nút nào vào trước được lấy ra trước, nút nào vào sau được lấy ra sau là hàng đợi không có ưu tiên

Trong thực tế có một dạng hàng đợi khác hoạt động theo cơ chế: nút nào có độ ưu tiên cao hơn sẽ được lấy ra trước, nút nào có độ ưu tiên thấp hơn thì lấy ra sau Hàng đợi lúc này gọi là hàng đợi có ưu tiên (priority queue)

Có 2 loại hàng đợi có ưu tiên:

Hàng đợi có ưu tiên tăng: nút có độ ưu tiên cao nhất được lấy ra

Hàng đợi có ưu tiên giảm: nút có độ ưu tiên giảm sẽ được lấy ra trước

Phần hiện thực hàng đợi ưu tiên sẽ được xem như bài tập

6 CHƯƠNG TRÌNH MINH HOẠ

Giả sử chúng ta có một kho hàng có tính chất: mặt hàng nào nhập kho trước sẽ xuất kho trước, mặt hàng nào nhập kho sau sẽ xuất kho sau Chương trình có các chức năng nhập kho, xuất kho, xem tồn kho…

//CHUONG TRINH DEMO QUAN LY KHO BANG HANG DOI

#include <stdio.h>

#include <stdlib.h>

Trang 14

#define MAXQUEUE 100

#define TRUE 1

#define FALSE 0

typedef struct mathang{

int mamh;

char tenmh[12];

};

struct queue{

int front,rear;

mathang nodes[MAXQUEUE];

};

void initialize(struct queue *pq){

pq->front=pq->rear=MAXQUEUE -1;

}

int empty(struct queue *pq){

if(pq->front==pq->rear)

return TRUE;

else

return FALSE;

}

void insert(struct queue *pq, mathang x){

if(pq->rear==MAXQUEUE-1)

pq->rear=0;

else

pq->rear++;

if(pq->rear==pq->front)

printf("Kho hang bi day");

else

pq->nodes[pq->rear]=x;

}

mathang remove(struct queue *pq){

if(pq->front==MAXQUEUE -1)

pq->front=0;

else

pq->front++;

return pq->nodes[pq->front];

}

void traverse(struct queue *pq){

int i;

Trang 15

printf("\n Kho khong con hang");

return;

}

if(pq->front==MAXQUEUE-1)

i=0;

else

i=pq->front+1;

while(i !=pq->rear){

printf("\n%11d%15s",pq->nodes[i].mamh,pq->nodes[i].tenmh);

if(i==MAXQUEUE-1){

i=0;

} else{

i++;

} }

printf("\n%11d%15s",pq->nodes[i].mamh,pq->nodes[i].tenmh);

}

void main(){

struct queue q;

int chucnang,front1;

mathang mh;

initialize(&q);

do{

printf("\n\n\t\t CHUONG TRINH QUAN LY KHO");

printf("\n\t\t NHAP TRUOC XUAT TRUOC");

printf("\n\n Cac chuc nang cua chuong trinh");

printf("\n 1 Nhap mot mat hang");

printf("\n 2 Xuat mot mat hang");

printf("\n 3 Xem mot mat hang chuan bi xuat");

printf("\n 4 Xem mat hang moi nhap");

printf("\n 5 Xem cac mat hang co trong kho");

printf("\n 6 Xuat toan bo kho hang");

printf("\n 0 Ket thuc chuong trinh");

printf("\n\n Chuc nang ban chon: ");

scanf("%d",&chucnang);

switch(chucnang){

case 1:

printf("\n Ma mat hang: ");

scanf("%d",&mh.mamh);

printf("\n Ten mat hang: ");

Trang 16

insert(&q,mh);

break;

case 2:

if(!empty(&q)){

mh=remove(&q);

printf("\n Mat hang xuat: Ma: %d Ten:

%s",mh.mamh,mh.tenmh);

} else printf("\n Kho khong con hang");

break;

case 3:

if(q.front==MAXQUEUE -1)

front1=0;

else

front1=q.front+1;

printf("\n Mat hang chuan bi xuat: Ma: %d Ten: %s

",q.nodes[front1].mamh,q.nodes[front1].tenmh);

break;

case 4:

printf("\n Mat hang moi nhap: Ma: %d Ten: %s", q.nodes[q.rear].mamh,q.nodes[q.rear].tenmh);

break;

case 5:

printf("\n Cac mat hang co trong kho: ");

printf("\n %11s%15s", "MA MAT HANG","TEN MAT HANG");

traverse(&q);

break;

case 6:

initialize(&q);

break;

} }while(chucnang !=0);

}

7 BÀI TẬP

1 Hiện thực hàng đợi và các tác vụ của hàng đợi bằng danh sách liên kết

2 Viết chương trình quản lý kho hàng dùng hàng đợi được hiện thực bằng danh sách liên kết

3 Viết chương trình hiện thực hàng đợi có độ ưu tiên

4 Biểu diễn biểu thức theo cú pháp Ba Lan Biểu thức nguyên là một dãy được thành lập

từ các biến kiểu nguyên nối với nhau bằng các phép toán 2 ngôi: +, -, *, / và các dấu ‘)’,

‘(’ Nguyên tắc đặc tên biến và thứ tự thực hiện các phép toán được thực hiện như sau:

Ngày đăng: 20/01/2014, 18:20

HÌNH ẢNH LIÊN QUAN

Hình sau đây mô tả hình ảnh của stack qua các tác vụ: - Tài liệu Giáo trình cấu trúc dữ liệu và giải thuật_Chương 3: Cấu trúc Stack & Queue pptx
Hình sau đây mô tả hình ảnh của stack qua các tác vụ: (Trang 1)

TỪ KHÓA LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w