栈和队列操作的实现(验证性实验)

栈和队列操作的实现(验证性实验)

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. 概要设计

  1. 为了实现程序功能,需要定义栈和队列的抽象数据类型。
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;
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值