NGĂN XẾP STACK 1 Stack ngăn xếp: - Stack là một đối tượng dùng để chứa các phần tử dữ liệu item một cách có thứ tự.. - Khi đưa một phần tử vào hoặc lấy một phần tử ra khỏi stack thì ta
Trang 1NGĂN XẾP
(STACK)
1) Stack (ngăn xếp):
- Stack là một đối tượng dùng để chứa các phần tử dữ liệu (item) một cách có thứ tự
- Khi đưa một phần tử vào hoặc lấy một phần tử ra khỏi stack thì ta đều thực hiện ở cùng một phía (từ phía đỉnh của stack)
- Phần tử (item) đưa vào sau sẽ được lấy ra trước, phần tử đưa vào trước sẽ được lấy ra sau Cách đưa vào và lấy ra như thế được gọi là LIFO (Last In First Out)
Các thao tác cơ bản trên stack:
- InitStack: khởi tạo một stack rỗng
- IsEmpty: kiểm tra stack có rỗng hay chưa
- IsFull: kiểm tra stack đầy hay chưa
- Push: đưa một phần tử (item) dữ liệu vào stack, việc đưa vào này có thể làm stack bị đầy
- Pop: lấy một phần tử (item) dữ liệu ra khỏi stack, việc này có thể làm stack bị rỗng
- Khi viết code hiện thực một stack, ta có thể dùng:
• Mảng một chiều
• Danh sách liên kết đơn
2) Hiện thực stack bằng mảng một chiều:
struct tstack
{
int *a; //mảng một chiều chưa các item của stack
int n; //cho biết kích thước của stack
int top; //quản lý đỉnh của stack
};
typedef struct tstack STACK;
a) Hàm khởi tạo stack:
void InitStack(STACK &s, int spt)//spt là số phần tử của stack
{
s.a=new int[spt];
if(s.a==NULL)
{
cout<<”Không đủ bộ nhớ để cấp phát!”;
exit(0);
}
s.n=spt;
60 21
37 11
Đáy stack
Đỉnh stack
3 2 1 0
‐1 Stack.top
Trang 2b) Hàm kiểm tra stack rỗng hay chưa:
bool IsEmpty(STACK s)
{
if(s.top==-1)
return true;
return false;
}
• Hàm kiểm tra stack bị đầy hay chưa:
bool IsFull(STACK s)
{
if(s.top==s.n-1)
return true;
return false;
}
c) Hàm đưa một phần tử vào stack:
bool Push(STACK &s, int x)
{
if(IsFull(s)==true)
return false; //không đưa vào được vì stack đã đầy
s.top++;
s.a[s.top]=x; //hoặc viết gọn lại là s.a[++s.top]=x
return true; // đưa vào thành công
}
d) Hàm lấy một phần tử ra khỏi stack:
bool Pop(STACK &s, int &x)
{
if(IsEmpty(s)==true)
return false; // lấy ra không thành công vì stack đã rỗng x=s.a[s.top ];
return true; //lấy ra thành công
}
e) Hàm kiểm tra phần tử ở đỉnh stack có giá trị bằng bao nhiêu:
bool CheckTop(STACK s, int &x)
{
if(IsEmpty(s)==true)
return false;
x=s.a[s.top];
return true;
}
f) Hàm xuất các phần tử có trong stack:
void OutputStack(STACK s)
{
int i;
if(IsEmpty(s)==true)
return;
for(i=s.top;i>=0;i )
cout<<s.a[i]<<” “;
cout<<”Đỉnh của stack đang ở tại vị trí:”<<s.top;
}
Trang 3g) Một ví dụ về hàm main cho bài lập trình stack bằng mảng một chiều:
void main()
{
bool over, empty;
STACK s;
int nn, x,i;
cout<<”Hãy cho biết kích thước của stack:;
cin>>nn; //số phần tử của stack
InitStack(s,nn);
cout<<”Thí nghiệm hàm Push:”;
for(i=0;i<s.n+1;i++) //cố tình push vào vượt kích thước stack
{
cout<<”Nhập giá trị để đưa vào stack, x=”;
cin>>x;
over=Push(s,x);
if(over==false)
cout<<”Stack bị tràn!”;
}
cout<<”Thí nghiệm hàm Pop:”;
for(i=0;i<s.n+3;i++) //cố tình pop ra vượt kích thước stack
{
empty=Pop(s,x);
cout<<”Giá trị x=”<<x;
if(empty==false)
cout<<”Stack đã rỗng!”;
}
}
3) Hiện thực stack bằng danh sách liên kết đơn:
- Sử dụng một danh sách liên kết đơn để hiện thực stack với đỉnh stack (biến top) chỉ vào phần tử đầu tiên của danh sách
- Push một phần tử (item) vào stack thì tương đương với hàm AddHead trong bài danh sách liên kết đơn
- Pop một phần tử (item) ra khỏi stack thì tương đương với hàm DeleteHead trong bài danh sách liên kết đơn
key
pDown
NULL
item
60
21
37
11
Đáy stack
Đỉnh stack
3 2 1 0
‐1
Stack.top
11
21
60
37 NULL s.Top
STACK s
Trang 4struct titem
{
int key;
struct titem *pDown;
};
typedef struct titem ITEM;
struct tstack
{
ITEM *Top;
int numOfItem;
};
typedef struct tstack STACK;
a) Hàm tạo một phần tử để chuẩn bị đưa vào stack
(Hàm này giống với hàm tạo node trong bài danh sách liên kết đơn)
ITEM *MakeItem(int x)
{
ITEM *t=new ITEM;
if(t==NULL)
{
cout<<"Stack is full!"<<endl;;
}
t->key=x;
t->pDown=NULL;
return t;
}
b) Hàm khởi động stack:
void InitStack(STACK &s)
{
s.Top=NULL;
s.numOfItem=0;
}
c) Hàm kiểm tra stack đã rỗng hay chưa
bool isEmpty(STACK s)
{
if(s.Top==NULL && s.numOfItem==0)
return true;
return false;
}
Trang 5d) Hàm kiểm tra stack đã đầy hay chưa:
bool isFull()
{
ITEM *t=new ITEM;
if (t==NULL)
return true;
delete t;
return false;
}
e) Hàm thêm một phần tử vào đỉnh của stack:
(Hàm này tương đương với hàm AddHead trong bài danh sách liên kết đơn Hàm addTop
để phục vụ cho hàm Push)
void addTop(STACK &s,ITEM *item)
{
if(s.Top==NULL)
{
}
item->pDown=s.Top;
s.Top=item;
}
f) Hàm đưa một phần tử vào stack
bool Push(STACK &s, int x)
{
if(isFull()==true)
return false;
ITEM *item=MakeItem(x);
addTop(s,item);
s.numOfItem++;
return true;
}
g) Hàm xóa một phần tử tại đỉnh stack:
(Hàm này tương đương với hàm DeleteHead trong bài danh sách liên kết đơn Hàm deleteTop để phục vụ cho hàm Pop)
void deleteTop(STACK &s)
{
if(s.Top==NULL) return;
ITEM *item=s.Top;
s.Top=s.Top->pDown;
delete item;
}
Trang 6h) Hàm lấy một phần tử ra khỏi đỉnh stack:
bool Pop(STACK &s, int &x)
{
if(isEmpty(s)==true)
return false;
x=s.Top->key;
deleteTop(s);
s.numOfItem ;
return true;
}
i) Hàm kiểm tra phần tử ở đỉnh stack có giá trị bằng bao nhiêu:
bool CheckTop(STACK s, int &x)
{
if(isEmpty(s)==NULL)
return false;
x=s.Top->key;
return true;
}
j) Hàm xuất các phần tử có trong stack:
void OutputStack(STACK s)
{
ITEM *i;
if(isEmpty(s)==true)
{
cout<<"Stack is empty!"<<endl;
}
for(i=s.Top;i!=NULL;i=i->pDown)
cout<<i->key<<" ";
cout<<endl<<"Number of items is "<<s.numOfItem<<endl;
cout<<endl;
}
k) Một ví dụ về hàm main cho bài lập trình stack bằng danh sách liên kết đơn:
void main()
{
STACK s;
int i,x;
bool check;
InitStack(s);
for(i=0;i<7;i++)
{
cout<<"Input a value = ";
cin>>x;
check=Push(s,x);
if(check==false)
cout<<"Stack is full!"<<endl;
Trang 7cout<<"After input, content of the stack is:"<<endl;
OutputStack(s);
cout<<"Start to pop out (the first time)"<<endl;
int n=s.numOfItem;
for(i=0;i<n-3;i++)
{
check=Pop(s,x);
if(check==true)
cout<<"Poped out x="<<x<<endl;
if(check==false)
cout<<"Stack is empty!"<<endl;
}
cout<<"After (the first time) pop out, content of the stack is:"<<endl;
OutputStack(s);
cout<<"Start to pop out (the second time)"<<endl;
n=s.numOfItem;
for(i=0;i<n+3;i++)
{
check=Pop(s,x);
if(check==true)
cout<<"Poped out x="<<x<<endl;
if(check==false)
cout<<"Stack is empty!"<<endl;
}
cout<<"After (the second) pop out, content of the stack is:"<<endl;
OutputStack(s);
cout<<endl;
}
GV: Võ Tấn Dũng votandung@yahoo.com Trường Cao Đẳng CNTT-TPHCM