栈和队列操作的实现(验证性实验)
1. 需求分析
要求:
(1) 建立一个顺序栈。
(2) 建立一个循环顺序队列。
(3) 分别实现栈和队列的基本操作
分析:
(1) 输入的形式和输入值的范围:按照屏幕提示输入数个int型数字
(2) 输出的形式:各个功能输出对应数个int型数字。
(3) 程序所能达到的功能:栈的基本操作:创建栈,创建栈,清空栈,判断栈是否为空栈,求栈长度,取栈顶,入栈,出栈,遍历栈;队列的基本操作:创建队列,求队列长度,添加节点,删除节点,销毁队列,清空队列,判断队列是否为空,取队列顶部,队列遍历。
(4) 测试数据:
栈操作的实现:
· 依次输入数据:1 2 3 4 5 6 7 8 9 10;
· 输出结果显示在屏幕上;
队列操作的实现:
· 依次输入数据:1 2 3 4 5 6 7 8 9 10;
· 输出结果显示在屏幕上;
· 再依次输入数据:11 12 13;
· 输出结果显示在屏幕上。
2. 概要设计
- 为了实现程序功能,需要定义栈和队列的抽象数据类型。
ADT Stack {
数据对象:
D={ ai | ai ∈ElemSet, i=1,2,...,n, n≥0 }
数据关系:
R1={ <ai-1, ai >| ai-1, ai∈D, i=2,...,n }
约定an 端为栈顶,a1 端为栈底。
typedef struct{
selemtype *base; //尾指针
selemtype *top; //头指针
int stacksize; //栈长
}sqstack; //栈结构
基本操作:
InitStack(&S)
操作结果:构造一个空栈S
DestroyStack (&S)
初始条件:栈S已存在
操作结果:销毁栈S
ClearStack (&S)
初始条件:栈S已存在
操作结果:将栈置为空栈
StackEmpty(&S)
初始条件:栈S已存在
操作结果:若S为空栈则返回TRUE,否则返回FALSE
StackLength(&S)
初始条件:栈S已存在
操作结果:返回S中数据元素的个数,即栈的长度
GetTop(&S, &e)
初始条件:栈S已存在
操作结果:用e返回S的栈顶元素
Push(&S, e)
初始条件:栈S已存在
操作结果:插入元素e为新的栈顶元素
Pop(&S, &e)
初始条件:栈S已存在且非空
操作结果:删除S的栈顶元素,并用e返回其值
StackTraverse(&S, visit())
初始条件:栈S已存在且非空
操作结果:从栈底到栈顶依次对S的每个数据元素调用函数visit(),一旦visit()失败,则操作失败
}ADT Stack
ADT Queue {
数据对象:
D={ai | ai∈ElemSet, i=1,2,...,n, n≥0}
数据关系:
R1={ <a i-1, ai > | ai-1, ai ∈D, i=2,...,n}
约定其中a1 端为队列头,an 端为队列尾
typedef struct{
qelemtype *base;
int front;
int rear;
}sqqueue; //队列结构
基本操作:
InitQueue(&Q)
操作结果:构造一个空队列Q。
DestroyQueue(&Q)
初始条件:队列Q已存在。
操作结果:队列Q被销毁,不再存在。
QueueEmpty(Q)
初始条件:队列Q已存在。
操作结果:若Q为空队列,则返回TRUE,否则返回FALSE。
QueueLength(Q)
初始条件:队列Q已存在。
操作结果:返回Q的元素个数,即队列的长度。
GetHead(Q,&e)
初始条件:Q为非空队列。
操作结果:用e返回Q的队头元素。
ClearQueue(&Q)
初始条件:队列Q已存在。
操作结果:将Q清为空队列。
EnQueue(&Q, e)
初始条件:队列Q已存在。
操作结果:插入元素e为Q的新的队尾元素
DeQueue(&Q, &e)
初始条件:Q为非空队列。
操作结果:删除Q的队头元素,并用e返回其值。
QueueTraverse(Q, visit())
初始条件:队列Q存在且非空
操作结果:从栈底到栈顶依次对S的每个数据元素调用函数visit(),一旦visit()失败,则操作失败
} ADT Queue
3.具体代码
- 栈操作的实现:
#include<stdio.h>
#include<stdlib.h>
#define STACK_INIT_SIZE 5
#define STACKINCREMENT 10
#define selemtype int
#define TRUE 1
#define FLASE 0
#define OK 1
#define ERROR 0
typedef struct{
selemtype *base; //尾指针
selemtype *top; //头指针
int stacksize; //栈长
}sqstack; //栈结构
int visit(selemtype *e) //打印节点
{
//输入的为指针
if(e == NULL)
{
//当指针指向null直接返回错误
return ERROR;
}
else
{
//否则打印指针指向的数据
printf("%d ",*e);
return OK;
}
}
void initstack(sqstack *s); //创建栈
void destroystack(sqstack *s); //销毁栈
void clearstack(sqstack *s); //清空栈
int stackempty(sqstack s); //判断栈是否为空栈
int stacklength(sqstack s); //求栈长度
int gettop(sqstack s,selemtype *e); //取栈顶
void push(sqstack *s,selemtype e); //入栈
int pop(sqstack *s,selemtype *e); //出栈
int stacktraverse(sqstack s,int (*visit)(selemtype *e)); //遍历栈
int main()
{
// int a;
sqstack stack;//先定义结构体
initstack(&stack);//创建栈
printf("是否为空栈:%d",stackempty(stack));
printf("\n请输入10个数:");
// scanf("%d",&a);
int i;
int n = 0;
for(;n < 10;n++)
{
scanf("%d",&i);//输入
push(&stack,i); //入栈
}
i=0;//使i重归0
printf("\n栈长度:%d",stacklength(stack));//输出栈的长度
gettop(stack,&i);//获取栈顶元素,存在i中
printf("\n栈顶元素:%d",i);//输出栈顶元素
printf("\n删除顶部3个元素:");
n = 0;
for(;n < 3;n++)
{
pop(&stack,&i);//弹出栈顶元素
printf("%d ",i);//输出删除的栈顶元素
}
printf("\n遍历栈");
stacktraverse(stack,visit);
printf("\n是否为空栈:%d",stackempty(stack));//判断是否为空栈
printf("\n清空栈");
clearstack(&stack);//清空
printf("\n是否为空栈:%d",stackempty(stack));//判断是否为空栈
destroystack(&stack);//销毁
if(stack.base == NULL&&stack.top ==NULL&&stack.stacksize ==0)
{
printf("\n销毁栈成功。");
}
return 0;
}
void initstack(sqstack *s) //创建栈
{
s->base = (selemtype*)malloc(STACK_INIT_SIZE*sizeof(int));// 为栈底部创空间
s->top = s->base;//初始,栈顶等于栈底
s->stacksize = STACK_INIT_SIZE;//栈长度为5
}
void destroystack(sqstack *s) //销毁栈
{
free(s->base);//释放base空间
s->base = NULL;
s->top = NULL;
s->stacksize = 0;//使长度为0
}
void clearstack(sqstack *s) //清空栈
{
s->base = (selemtype*)malloc(s->stacksize*sizeof(int));
s->top = s->base;
//相当于重新初始化设置
}
int stackempty(sqstack s) //判断栈是否为空栈
{
if(s.base == s.top&&s.top != NULL)//顶部和底部位置相同,且不为空
{
return TRUE;
}
else
{
return FLASE;
}
}
int stacklength(sqstack s) //求栈长度
{
selemtype *p=s.base;//p指向栈底元素
int n=0;//用于for循环
for(;p != s.top||n >= s.stacksize;p++)
{
n++;
}
return n;//返回栈长度
}
int gettop(sqstack s,selemtype *e) //取栈顶
{
if(s.top == s.base)//如果栈顶=栈底,则栈为空
{
return ERROR;
}
else
{
*e = *(s.top-1);
return OK;
}
}
void push(sqstack *s,selemtype e) //入栈
{
if((stacklength(*s)+1) >= s->stacksize)
{
s->base = (selemtype*)realloc(s->base,(s->stacksize+STACKINCREMENT)*sizeof(selemtype));
s->stacksize += STACKINCREMENT;//入栈10个元素
s->top =s->base+s->stacksize-STACKINCREMENT-1;
}
*s->top = e;//先存放元素
s->top++;//再让top位置往后移
}
int pop(sqstack *s,selemtype *e) //出栈
{
if(stackempty(*s) != TRUE)
{
*e = *(--s->top);
return OK;
}
else
{
return ERROR;
}
}
int stacktraverse(sqstack s,int (*visit)(selemtype *e)) //遍历栈
{
selemtype *p = s.base;
for(;p != s.top;p++)
{
if(!visit(p))
{
return ERROR;
}
}
return OK;
}
- 队列操作的实现:
#include<stdio.h>
#include<stdlib.h>
#define MAXQSIZE 11
#define qelemtype int
#define OVERFLOW -1
#define OK 1
#define ERROR 0
typedef struct{
qelemtype *base;//队列(指针型数组)
int front;//头
int rear;//尾
}sqqueue; //队列结构
int visit(qelemtype e) //打印节点
{
if(printf("%d ",e))
{
return OK;
}
else
{
return ERROR;
}
}
void initqueue(sqqueue *q); //创建队列
int queuelength(sqqueue q); //求队列长度
int enqueue(sqqueue *q,qelemtype e); //添加节点
int dequeue(sqqueue *q,qelemtype *e); //删除节点
void destroyqueue(sqqueue *q); //销毁队列
int clearqueue(sqqueue *q); //清空队列
int queueempty(sqqueue q); //判断队列是否为空
int gethead(sqqueue q,qelemtype *e); //取队列顶部
int queuetraverse(sqqueue q,int (*visit)(qelemtype e)); //队列遍历
int main()
{
sqqueue queue;//定义队列
initqueue(&queue);//初始化队列
printf("队列长度:%d",queuelength(queue));//求队列长度
printf("是否为空队列:%d",queueempty(queue));//判断是否为空队列
printf("\n请输入10个数:");//往队列中放置10个数字
int i;//用于储存输入量
int n = 0;//用于for循环
for(;n < 10;n++)
{
scanf("%d",&i);
enqueue(&queue,i); //将输入量置入队列
}
i=0;//将i重新设置为0
printf("\n队列长度:%d",queuelength(queue));//再求队列长度
gethead(queue,&i);//取出队列头
printf("\n队头元素:%d",i);//输出队头元素
printf("\n删除队头3个元素:");//删除3个元素
n = 0;
for(;n < 3;n++)
{
dequeue(&queue,&i);//出队3次
printf("%d ",i);//同时输出元素
}
printf("\n遍历队列");//遍历
queuetraverse(queue,visit);
printf("\n请输入3个数:");
n = 0;
for(;n < 3;n++)
{
scanf("%d",&i);//i为输入的读取
enqueue(&queue,i); //再次添加节点
}
printf("\n遍历队列");
queuetraverse(queue,visit);
printf("是否为空队列:%d",queueempty(queue));//判断是否为空队列
printf("\n清空队列");
clearqueue(&queue);//清空
printf("\n是否为空队列:%d",queueempty(queue));
destroyqueue(&queue);
if(queue.base == NULL&&queue.front == 0&&queue.rear == 0)
{
printf("\n销毁栈成功。");
}
return 0;
}
void initqueue(sqqueue *q) //创建队列
{
q->base = (qelemtype *)malloc(MAXQSIZE*sizeof(qelemtype));//分配空间
if(!q->base)
{
exit(OVERFLOW);
}
q->front = q->rear = 0;//初始收尾都是0
}
int queuelength(sqqueue q) //求队列长度
{
return (q.rear - q.front + MAXQSIZE) % MAXQSIZE;//循环队列求队列长度的公式
}
int enqueue(sqqueue *q,qelemtype e) //添加节点
{
if((q->rear + 1) % MAXQSIZE == q->front)//判断是否队列满
{
return(ERROR);
}
q->base[q->rear] = e;//如果队列未满,则将数据添加进去
q->rear = (q->rear + 1) % MAXQSIZE;//尾节点后移
return OK;
}
int dequeue(sqqueue *q,qelemtype *e) //删除节点
{
if(q->front == q->rear)//如果为空队列
{
return ERROR;
}
*e = q->base[q->front];//保存删除节点的e的数据
q->front = (q->front + 1) % MAXQSIZE;//头部位置后移
return OK;
}
void destroyqueue(sqqueue *q) //销毁队列
{
free(q->base);//清除空间
q->base =NULL;//数组置为空
q->front = q->rear =0;//重新初始化为0
}
int clearqueue(sqqueue *q) //清空队列
{
if(q)//若数组非空
{
q->front = q->rear = 0;//只需要让头尾指针重新置0即可
return OK;
}
else
{
return ERROR;
}
}
int queueempty(sqqueue q) //判断队列是否为空
{
if(q.front == q.rear)
{
return OK;
}
else
{
return ERROR;
}
}
int gethead(sqqueue q,qelemtype *e) //取队列顶部
{
if(!queueempty(q))
{
*e = q.base[q.front];//获取队列顶部元素 ,用e储存
return OK;
}
else
{
return ERROR;
}
}
int queuetraverse(sqqueue q,int (*visit)(qelemtype e)) //队列遍历
{
int i = q.front;//首先令i为队列头指针的位置
for(;i != q.rear;i++)//遍历队列
{
if(!visit(q.base[i]))//利用visit函数
{
return ERROR;
}
if(i >= (MAXQSIZE-1))//对于循环队列而言,到达数组底部还未遍历完的话,重新回到队列头部
{
i = -1;
}
}
return OK;
}