栈的操作.docx
- 文档编号:28557272
- 上传时间:2023-07-19
- 格式:DOCX
- 页数:19
- 大小:20.61KB
栈的操作.docx
《栈的操作.docx》由会员分享,可在线阅读,更多相关《栈的操作.docx(19页珍藏版)》请在冰豆网上搜索。
栈的操作
实验三栈和队列
实验目的:
(1)熟悉栈的特点(先进后出)及栈的基本操作,如入栈、出栈等,掌握栈的基本操作在栈的顺序存储结构和链式存储结构上的实现;
(2)熟悉队列的特点(先进先出)及队列的基本操作,如入队、出队等,掌握队列的基本操作在队列的顺序存储结构和链式存储结构上的实现。
3.2实验要求:
(1)复习课本中有关栈和队列的知识;
(2)用C语言完成算法和程序设计并上机调试通过;
(3)撰写实验报告,给出算法思路或流程图和具体实现(源程序)、算法分析结果(包括时间复杂度、空间复杂度以及算法优化设想)、输入数据及程序运行结果(必要时给出多种可能的输入数据和运行结果)。
3.3基础实验
[实验1]栈的顺序表示和实现
实验内容与要求:
编写一个程序实现顺序栈的各种基本运算,并在此基础上设计一个主程序,完成如下功能:
(1)初始化顺序栈
(2)插入元素
(3)删除栈顶元素
(4)取栈顶元素
(5)遍历顺序栈
(6)置空顺序栈
分析:
栈的顺序存储结构简称为顺序栈,它是运算受限的顺序表。
对于顺序栈,入栈时,首先判断栈是否为满,栈满的条件为:
p->top==MAXNUM-1,栈满时,不能入栈;否则出现空间溢出,引起错误,这种现象称为上溢。
出栈和读栈顶元素操作,先判栈是否为空,为空时不能操作,否则产生错误。
通常栈空作为一种控制转移的条件。
注意:
(1)顺序栈中元素用向量存放
(2)栈底位置是固定不变的,可设置在向量两端的任意一个端点
(3)栈顶位置是随着进栈和退栈操作而变化的,用一个整型量top(通常称top为栈顶指针)来指示当前栈顶位置
参考程序:
#include<>
#include<>
#defineMAXNUM20
#defineElemTypeint
/*定义顺序栈的存储结构*/
typedefstruct
{ElemTypestack[MAXNUM];
inttop;
}SqStack;
/*初始化顺序栈*/
voidInitStack(SqStack*p)
{if(!
p)
printf("Eorror");
p->top=-1;
}
/*入栈*/
voidPush(SqStack*p,ElemTypex)
{if(p->top {p->top=p->top+1; p->stack[p->top]=x; } else printf("Overflow! \n"); } /*出栈*/ ElemTypePop(SqStack*p) {ElemTypex; if(p->top! =0) {x=p->stack[p->top]; printf("以前的栈顶数据元素%d已经被删除! \n",p->stack[p->top]); p->top=p->top-1; return(x); } else {printf("Underflow! \n"); return(0); } } /*获取栈顶元素*/ ElemTypeGetTop(SqStack*p) {ElemTypex; if(p->top! =0) {x=p->stack[p->top]; return(x); } else {printf("Underflow! \n"); return(0); } } /*遍历顺序栈*/ voidOutStack(SqStack*p) {inti; printf("\n"); if(p->top<0) printf("这是一个空栈! "); printf("\n"); for(i=p->top;i>=0;i--) printf("第%d个数据元素是: %6d\n",i,p->stack[i]); } /*置空顺序栈*/ voidsetEmpty(SqStack*p) { p->top=-1; } /*主函数*/ main() {SqStack*q; inty,cord;ElemTypea; do{ printf("\n"); printf("第一次使用必须初始化! \n"); printf("\n"); printf("\n主菜单\n"); printf("\n1初始化顺序栈\n"); printf("\n2插入一个元素\n"); printf("\n3删除栈顶元素\n"); printf("\n4取栈顶元素\n"); printf("\n5置空顺序栈\n"); printf("\n6结束程序运行\n"); printf("\n--------------------------------\n"); printf("请输入您的选择(1,2,3,4,5,6)"); scanf("%d",&cord); printf("\n"); switch(cord) {case1: {q=(SqStack*)malloc(sizeof(SqStack)); InitStack(q); OutStack(q); }break; case2: {printf("请输入要插入的数据元素: a="); scanf("%d",&a); Push(q,a); OutStack(q); }break; case3: {Pop(q); OutStack(q); }break; case4: {y=GetTop(q); printf("\n栈顶元素为: %d\n",y); OutStack(q); }break; case5: {setEmpty(q); printf("\n顺序栈被置空! \n"); OutStack(q); }break; case6: exit(0); } }while(cord<=6); } [实验2]栈的链式表示和实现 实验内容与要求: 编写一个程序实现链栈的各种基本运算,并在此基础上设计一个主程序,完成如下功能: (1)初始化链栈 (2)链栈置空 (3)入栈 (4)出栈 (5)取栈顶元素 (6)遍历链栈 分析: 链栈是没有附加头结点的运算受限的单链表。 栈顶指针就是链表的头指针。 注意: (1)LinkStack结构类型的定义可以方便地在函数体中修改top指针本身 (2)若要记录栈中元素个数,可将元素个数属性放在LinkStack类型中定义。 (3)链栈中的结点是动态分配的,所以可以不考虑上溢。 参考程序: #include"" #include"" #include"" typedefintElemtype; typedefstructstacknode{ Elemtypedata; stacknode*next; }StackNode; typedefstruct{ stacknode*top;=1;} printf("themazeis: \n"); =1;top[i].y=0; maze[1][0]=2; /*回溯算法*/ do{ if(top[i].c<5) ==5&&top[i].y==9),top[j].y);} printf("\n"); ][top[i].y]=0; top[i].c=1; i--; top[i].c+=1; continue;} switch(top[i].c) ][top[i].y+1]==0) {i++; top[i].x=top[i-1].x; top[i].y=top[i-1].y+1; maze[top[i].x][top[i].y]=2;} else {top[i].c+=1;} break;} case2: {if(maze[top[i].x-1][top[i].y]==0) {i++; top[i].x=top[i-1].x-1; top[i].y=top[i-1].y; maze[top[i].x][top[i].y]=2;} else {top[i].c+=1;} break;} case3: {if(maze[top[i].x][top[i].y-1]==0) {i++; top[i].x=top[i-1].x; top[i].y=top[i-1].y-1; maze[top[i].x][top[i].y]=2;} else {top[i].c+=1;} break;} case4: {if(maze[top[i].x+1][top[i].y]==0) {i++; top[i].x=top[i-1].x+1; top[i].y=top[i-1].y; maze[top[i].x][top[i].y]=2;} else { top[i].c+=1;} break;} } } else ][top[i].y]=0; top[i].c=1; i--; top[i].c+=1;} }while (1); } [实验2]停车场管理 实验内容与要求: 设停车场内只有一个可停放n辆汽车的狭长通道,且只有一个大门可供汽车进出。 汽车在停车场内按车辆到达时间的先后顺序,依次由北向南排列(大门在最南端,最先到达的第一辆车停放在车场的最北端),若车场内已停满n辆汽车,则后来的汽车只能在门外的便道上等候,一旦有车开走,则排在便道上的第一辆车即可开入;当停车场内某辆车要离开时,在它之后开入的车辆必须先退出车场为它让路,待该辆车开出大门外,其它车辆再按原次序进入车场,每辆停放在车场的车在它离开停车场时必须按它停留的时间长短交纳费用。 试为停车场编制按上述要求进行管理的模拟程序。 分析: 综合利用栈和队列模拟停车场管理,学习利用栈和队列解决实际问题。 以栈模拟停车场,以队列模拟车场外的便道,按照从终端读入的输入数据序列进行模拟管理。 每一组输入数据包括三个数据项: 汽车“到达”或“离去”信息、汽车牌照号码及到达或离去的时刻,对每一组输入数据进行操作后的输出数据为: 若是车辆到达,则输出汽车在停车场内或便道上的停车位置;若是车离去;则输出汽车在停车场内停留的时间和应交纳的费用(在便道上停留的时间不收费)。 栈以顺序结构实现,队列以链表实现。 需另设一个栈,临时停放为给要离去的汽车让路而从停车场退出来的汽车,也用顺序存储结构实现。 输入数据按到达或离去的时刻有序。 栈中每个元素表示一辆汽车,包含两个数据项: 汽车的牌照号码和进入停车场的时刻。 设n=2,输入数据为: (‘A’,1,5),(‘A’,2,10),(‘D’,1,15),(‘A’,3,20),(‘A’,4,25),(‘A’,5,30),(‘D’,2,35),(‘D’,4,40),(‘E’,0,0)。 每一组输入数据包括三个数据项: 汽车“到达”或“离去”信息、汽车牌照号码及到达或离去的时刻,其中,‘A’表示到达;‘D’表示离去,‘E’表示输入结束。 参考程序: #include<> #include<> #include<> #defineMAX2/*车库容量*/ #defineprice/*每车每分钟费用*/ typedefstructtime{ inthour; intmin; }Time;/*时间结点*/ typedefstructnode{ charnum[10]; Timereach; Timeleave; }CarNode;/*车辆信息结点*/ typedefstructNODE{ CarNode*stack[MAX+1]; inttop; }SeqStackCar;/*模拟车站*/ typedefstructcar{ CarNode*data; structcar*next; }QueueNode; typedefstructNode{ QueueNode*head; QueueNode*rear; }LinkQueueCar;/*模拟通道*/ voidInitStack(SeqStackCar*);/*初始化栈*/ intInitQueue(LinkQueueCar*);/*初始化便道*/ intArrival(SeqStackCar*,LinkQueueCar*);/*车辆到达*/ voidLeave(SeqStackCar*,SeqStackCar*,LinkQueueCar*);/*车辆离开*/ voidList(SeqStackCar,LinkQueueCar);/*显示存车信息*/ voidmain() {SeqStackCarEnter,Temp; LinkQueueCarWait; intch; InitStack(&Enter);/*初始化车站*/ InitStack(&Temp);/*初始化让路的临时栈*/ InitQueue(&Wait);/*初始化通道*/ while (1) {printf("\n1.车辆到达"); printf("2.车辆离开"); printf("3.列表显示"); printf("4.退出系统\n"); while (1) {scanf("%d",&ch); if(ch>=1&&ch<=4)break; elseprintf("\n请选择: 1|2|3|4."); } switch(ch) {case1: Arrival(&Enter,&Wait);break;/*车辆到达*/ case2: Leave(&Enter,&Temp,&Wait);break;/*车辆离开*/ case3: List(Enter,Wait);break;/*列表打印信息*/ case4: exit(0);/*退出主程序*/ default: break; }}} voidInitStack(SeqStackCar*s)/*初始化栈*/ {inti; s->top=0; for(i=0;i<=MAX;i++) s->stack[s->top]=NULL;} intInitQueue(LinkQueueCar*Q)/*初始化便道*/ {Q->head=(QueueNode*)malloc(sizeof(QueueNode)); if(Q->head! =NULL) {Q->head->next=NULL; Q->rear=Q->head; return (1);} elsereturn(-1);} voidPRINT(CarNode*p,introom)/*打印出站车的信息*/ {intA1,A2,B1,B2; printf("\n请输入离开的时间: /**: **/"); scanf("%d: %d",&(p->,&(p->); printf("\n离开车辆的车牌号为: "); puts(p->num); printf("\n其到达时间为: %d: %d",p->,p->; printf("离开时间为: %d: %d",p->,p->; A1=p->; A2=p->; B1=p->; B2=p->; printf("\n应交费用为: %2.1f元",((B1-A1)*60+(B2-A2))*price); free(p); } intArrival(SeqStackCar*Enter,LinkQueueCar*W)/*车辆到达*/ {CarNode*p; QueueNode*t; p=(CarNode*)malloc(sizeof(CarNode)); flushall(); printf("\n请输入车牌号(例: 陕A1234): "); gets(p->num); if(Enter->top {Enter->top++; printf("\n车辆在车场第%d位置.",Enter->top); printf("\n请输入到达时间: /**: **/"); scanf("%d: %d",&(p->,&(p->); Enter->stack[Enter->top]=p; return (1);} else/*车场已满,车进便道*/ {printf("\n该车须在便道等待! "); t=(QueueNode*)malloc(sizeof(QueueNode)); t->data=p; t->next=NULL; W->rear->next=t; W->rear=t; return (1);}} voidLeave(SeqStackCar*Enter,SeqStackCar*Temp,LinkQueueCar*W) {/*车辆离开*/ inti,room; CarNode*p,*t; QueueNode*q; /*判断车场内是否有车*/ if(Enter->top>0)/*有车*/ {while (1)/*输入离开车辆的信息*/ {printf("\n请输入车在车场的位置/1--%d/: ",Enter->top); scanf("%d",&room); if(room>=1&&room<=Enter->top)break;} while(Enter->top>room)/*车辆离开*/ {Temp->top++; Temp->stack[Temp->top]=Enter->stack[Enter->top]; Enter->stack[Enter->top]=NULL; Enter->top--; } p=Enter->stack[Enter->top]; Enter->stack[Enter->top]=NULL; Enter->top--; while(Temp->top>=1) {Enter->top++; Enter->stack[Enter->top]=Temp->stack[Temp->top]; Temp->stack[Temp->top]=NULL; Temp->top--;} PRINT(p,room); /*判断通道上是否有车及车站是否已满*/ if((W->head! =W->rear)&&Enter->top {q=W->head->next; t=q->data; Enter->top++; printf("\n便道的%s号车进入车场第%d位置.",t->num,Enter->top); printf("\n请输入现在的时间/**: **/: "); scanf("%d: %d",&(t->,&(t->); W->head->next=q->next; if(q==W->rear)W->rear=W->head; Enter->stack[Enter->top]=t; free(q);} elseprintf("\n便道里没有车.\n");} elseprintf("\n车场里没有车.");/*没车*/} voidList1(SeqStackCar*S)/*列表显示车场信息*/ {inti; if(S->top>0)/*判断车站内是否有车*/ {printf("\n车场: "); printf("\n位置到达时间车牌号\n"); for(i=1;i<=S->top;i++) {printf("%d",i); printf("%d: %d",S->stack[i]->,S->stack[i]->; puts(S->stack[i]->num);}} elseprintf("\n车场里没有车");} voidList2(LinkQueueCar*W)/*列表显示便道信息*/ {QueueNode*p; p=W->head->next; if(W->head! =W->rear)/*判断通道上是否有车*/ {printf("\n等待车辆的号码为: "); while(p! =NULL) {puts(p->data->num); p=p->next;}} elseprintf("\n便道里没有车.");} voidList(SeqStackCarS,LinkQueueCarW) {intflag,tag; flag=1; while(flag) {printf("\n请选择1|2|3: "); printf("\n1.车场\n2.便道\n3.返回\n"); while (1) {scanf("%d",&tag); if(tag>=1||tag<=3)break; elseprintf("\n请选择1|2|3: "); }switch(tag) {case1: List1(&S);break;/*列表显示车场信息*/ case2: List2(&W);break;/*列表显示便道信息*/ case3: flag=0;break; default: break;}}} 思考题: (1)读栈顶元素的算法与退栈顶元素的算法有何区别? (2)如果一个程序中要用到两个栈,为了不发生上溢错误,就必须给每个栈预先分配一个足够大的存储空间。 若每个栈都预分配过大的存储空间,势必会造成系统空间紧张。 如何解决这个问题? (3)栈的两种存储结构在判别栈空与栈满时,所依据的条件有何不同? (4)在程序中同时使用两个以上的栈时,使用顺序栈共享邻接空间则很难实现,能否通过链栈来方便地实现? 如何实现? (5)简述栈和队列的共同点和不同点。 它们为什么属于线性表? (6)在顺序队列中,当队尾指针已经指向了队列的最后一个位置时,但事实上队列中可能还有空位置。 此时若有元素入列,就会发生“假溢出”。 如何解决这个问题? (7)链栈只有一个top指针,对于链队列,为什么要设计一个头指针和一个尾指针? (8)一个程序中如果要用到两个栈时,可通过两个栈共享一维数组来实现。 即双向栈共享邻接空间。 如果一个程序中要用到两个队列,能否实现? 如何实现? 假设以带头结点的循环链表表示队列,并且只设一个指针指向队尾元素结点(注意: 不设头指针),试编写相应的队列初始化、入
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作
![提示](https://static.bdocx.com/images/bang_tan.gif)