文章目錄
一、實驗目的
(1)掌握棧的鏈式存儲結構;
(2)掌握棧的操作特性;
(3)掌握基於鏈棧的基本操作的實現方法。
二、實驗內容
(1)建立一個空棧;
(2)對已建立的棧進行插入、刪除、取棧頂元素等基本操作。
三、問題分析
棧 (stack) 是限定僅在表尾進行插入或刪除操作的線性表。對棧來說,表尾端有其特殊含義,稱爲棧頂 (top)
, 表頭端稱爲棧底 (bottom)
。不含元素的空表稱爲空棧。棧的修改是按後進先出
的原則進行的,棧又稱爲後進先出的線性表。
鏈棧是指採用鏈式存儲結構實現的棧。通常鏈棧用單鏈表來表示,鏈棧的結點結構與單鏈表的結構相同,在此用StackNode
表示。鏈棧有着初始化、入棧、出棧、去棧頂元素等操作。
四、算法設計
1、主要數據結構的設計
1.1 鏈棧的入棧
①爲入棧元素 e 分配空間,用指針 p 指向。
②將新結點數據域置爲e。
③將新結點插入棧頂。
④修改棧頂指針爲 p。
入棧示意圖
1.2 鏈棧的出棧
①判斷棧是否爲空,若空則返回ERROR。
②將棧頂元素賦給e。
③臨時保存棧頂元素的空間,以備釋放。
④修改棧頂指針,指向新的棧頂元素。
⑤釋放原棧頂元素的空間。
出棧示意圖
1.3 取棧頂元素
當棧非空時, 此操作返回當前棧頂元素的值, 棧頂指針S保持不變。
2、算法設計
2.1 鏈棧初始化算法
Status InitStack(LinkStack &S){
//構造一個空棧S,棧頂指針置空
S = NULL;
return OK;
}
2.2 入棧操作算法
Status Push (LinkStack &S, SElenType e){//在棧頂插人元素e
p-new StackNode; //生成新結點
p->data=e; //將新結點數據城置爲e
p->next=S; //將新結點插人棧頂
S=p; //修改棧頂指針爲p
return OK;
}
2.3 出棧操作算法
Status Pop (LinkStack &S, SElemType &e){//刪除s的棧頂元素,用e返回其值
if(S==NULL) return ERROR; //棧空
e=S->data; //將棧頂元素賦給e
p=S; //用p臨時保存棧頂元素空間,以備釋放
S=S->next; //修改棧頂指針
delete p; //釋放原棧頂元素的空間
return OK;
}
2.4 取棧頂元素算法
SElemtype GetTop(LinkStack S){
//返回S的棧頂元素,不修改棧頂指針
if(S!=NULL)
return S->data;
}
五、代碼實現
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
typedef int SElemtype;
typedef struct Node{
SElemtype data;
struct Node *next;
}StackNode,*LinkStack;
//初始化棧
int InitStack(LinkStack &S){
S = new StackNode;
S->next = NULL;
return OK;
}
int DestroyStack(LinkStack &S){
LinkStack p;
while(S){
p = S;
S = S->next;
delete p;
}
return OK;
}
//清空棧
void ClearStack(LinkStack S){
LinkStack p,q;
p = S->next;
while(p){
q = p->next;
delete p;
p = q;
}
S->next = NULL;//頭指針指針域爲空,空棧
}
//判斷鏈棧是否爲空
int StackEmply(LinkStack S){
return(S->next==NULL);
}
//入棧操作
void PushStack(LinkStack S,SElemtype e){
LinkStack p;
p = new StackNode;
p->data = e;
p->next = S->next;
S->next = p;
}
//出棧操作
int PopStack(LinkStack S,SElemtype &e){
LinkStack p;
if(StackEmply(S))
return ERROR;
p = S->next;
e = p->data;
S->next = p->next;
delete p;
return OK;
}
//取棧頂元素
int GetTop(LinkStack S,SElemtype e){
LinkStack p;
if(StackEmply(S))
return ERROR;
p = S->next;
e = p->data;
return OK;
}
//輸出鏈棧
void DispStack(LinkStack S){
LinkStack p = S->next;
printf("鏈棧爲:");
if(StackEmply(S)){
printf("棧空!\n");
return;
}
while(p){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
//顯示菜單
void Showmenu(){
printf("\n ---鏈棧基本操作--- \n");
printf("*******************************\n");
printf("* 1、初始化鏈棧 *\n");
printf("* 2、創建鏈棧 *\n");
printf("* 3、入棧操作 *\n");
printf("* 4、出棧操作 *\n");
printf("* 5、取棧頂元素 *\n");
printf("* 0、退出程序 *\n");
printf("*******************************\n");
printf("請選擇菜單(0-5):");
}
void Stack(){
int choice,m,e;
SElemtype item;
LinkStack S;
int flag = 0;
while(choice){
Showmenu();
scanf("%d",&choice);
switch(choice){
case 1:
if(InitStack(S)){
printf("初始化鏈棧成功!\n");
flag = 1;
}else
printf("初始化鏈棧失敗!\n");
break;
case 2:
if(flag){
printf("請輸入鏈棧長度:");
scanf("%d",&m);
for(int i = 0;i<m;i++){
e = rand()%20+1;
PushStack(S,e);
}
DispStack(S);
}else
printf("初始化鏈棧失敗!\n");
break;
case 3:
if(flag){
printf("請輸入入棧元素值:");
scanf("%d",&item);
PushStack(S,item);
printf("元素已入棧!\n");
DispStack(S);
}else{
printf("鏈棧不存在,操作失敗!\n");
}
break;
case 4:
if(flag){
if(PopStack(S,item))
printf("出棧元素爲:%d !\n",item);
else printf("棧空!\n");
DispStack(S);
}else{
printf("鏈棧不存在,操作失敗!\n");
}
break;
case 5:
if(flag){
if(GetTop(S,item))
printf("棧頂元素爲:%d!\n",item);
else printf("棧空!\n");
DispStack(S);
}
else{
printf("鏈棧不存在,操作失敗!\n");
}
break;
case 0:
printf("\t程序結束!\t\n");
DestroyStack(S);
break;
default:
printf("選擇錯誤,請重新選擇!!\n");
break;
}
}
}
//主函數
int main(){
Stack();
return 0;
}
作者文壇寫於2020年5月10日