第四次作业: 栈和队列

| 这个作业属于哪个课程 | https://edu.cnblogs.com/campus/qdu/DS2020 |
| ---- | ---- | ---- |
| 这个作业要求在哪里 | https://edu.cnblogs.com/campus/qdu/DS2020/homework/11296 |
| 这个作业的目标 | 理解栈、队列的概念,掌握入栈、出栈、入队、出队的操作 |
| 学号 | 2018204195 |

一、实验目的
1、掌握栈的结构特性及其入栈,出栈操作;
2、掌握队列的结构特性及其入队、出队的操作,掌握循环队列的特点及其操作。

二、实验预习
说明以下概念:
1、顺序栈:
顺序栈是栈的顺序实现。顺序栈是指利用顺序存储结构实现的栈。采用地址连续的存储空间(数组)依次存储栈中数据元素,由于入栈和出栈运算都是在栈顶进行,而栈底位置是固定不变的,可以将栈底位置设置在数组空间的起始处;栈顶位置是随入栈和出栈操作而变化的,故需用一个整型变量top来记录当前栈顶元素在数组中的位置。
2、链栈:
链式栈是一种数据存储结构,可以通过单链表的方式来实现,使用链式栈的优点在于它能够克服用数组实现的顺序栈空间利用率不高的特点,但是需要为每个栈元素分配额外的指针空间用来存放指针域。由于只能在链表头部进行操作,故链栈没有必要像单链表那样需要附加头结点。栈顶指针就是链表的头指针。
3、循环队列:
为充分利用向量空间,克服"假溢出"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量。存储在其中的队列称为循环队列(Circular Queue)。循环队列是把顺序队列首尾相连,把存储队列元素的表从逻辑上看成一个环,成为循环队列。循环队列就是将队列存储空间的最后一个位置绕到第一个位置,形成逻辑上的环状空间,供队列循环使用。在循环队列结构中,当存储空间的最后一个位置已被使用而再要进入队运算时,只需要存储空间的第一个位置空闲,便可将元素加入到第一个位置,即将存储空间的第一个位置作为队尾。
4、链队:
链队是指采用链式存储结构实现的队列,它的基本操作为:初始化链队、销毁链队、清空链队、检测链队是否为空、返回链队的元素个数、返回链队头元素、向队尾插入元素、删除并返回队头元素、遍历链队。

三、实验内容和要求

1、阅读下面程序,将函数Push和函数Pop补充完整。要求输入元素序列1 2 3 4 5 e,运行结果如下所示。

#include<stdio.h>
#include<malloc.h>
#define ERROR 0
#define OK 1
#define STACK_INT_SIZE 10  /*存储空间初始分配量*/
#define STACKINCREMENT 5  /*存储空间分配增量*/
typedef  int ElemType; /*定义元素的类型*/
typedef struct{
    ElemType *base;
    ElemType *top;
    int stacksize;     /*当前已分配的存储空间*/
}SqStack;

int InitStack(SqStack *S);   /*构造空栈*/
int push(SqStack *S,ElemType e); /*入栈*/
int Pop(SqStack *S,ElemType *e);  /*出栈*/
int CreateStack(SqStack *S);     /*创建栈*/
void PrintStack(SqStack *S);   /*出栈并输出栈中元素*/

int InitStack(SqStack *S){
    S->base=(ElemType *)malloc(STACK_INT_SIZE *sizeof(ElemType));
    if(!S->base) return ERROR;
    S->top=S->base;
    S->stacksize=STACK_INT_SIZE;
    return OK;
}/*InitStack*/

int Push(SqStack *S,ElemType e){
    if(S->top-S->base==S->stacksize)
	{
		int i=S->stacksize-1;
		ElemType *pt;
		pt=(ElemType *)malloc(2*S->stacksize*sizeof(ElemType));
		while(i>=0)
		{
			*(pt+i)=*(S->base+i);
			i--;
		}
		free(S->base);
		S->base=pt;
		S->top=pt+S->stacksize;
		S->stacksize*=2;
	}
	*(S->top)=e;
	S->top++;
	return OK;
}/*Push*/

int Pop(SqStack *S,ElemType *e){
   if(S->top>S->base)
	{
		S->top--;
		*e=*(S->top);
		return OK;
	}
	else
	{
		free(S->base);
		return ERROR;
	}
}/*Pop*/

int CreateStack(SqStack *S){
    int e;
    if(InitStack(S))
        printf("Init Success!\n");
    else{
        printf("Init Fail!\n");
        return ERROR;
    }
    printf("input data:(Terminated by inputing a character)\n");
    while(scanf("%d",&e))
        Push(S,e);
    return OK;
}/*CreateStack*/

void PrintStack(SqStack *S){
    ElemType e;
    while(Pop(S,&e))
        printf("%3d",e);
}/*Pop_and_Print*/

int main(){
    SqStack ss;
    printf("\n1-createStack\n");
    CreateStack(&ss);
    printf("\n2-Pop&Print\n");
    PrintStack(&ss);
    return 0;
}

运行结果:

算法分析:输入元素序列1 2 3 4 5,为什么输出序列为5 4 3 2 1?体现了栈的什么特性?
按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。当main函数调用PrintStack(&ss)时,程序转到函数中,而在该函数体内,又调用了int Pop(SqStack *S,ElemType *e),此函数的功能是栈S的栈顶元素退栈并返回其值,这体现了栈是只允许在表的一端进行操作的线性表且具有先进后出的特性。

2、在第1题的程序中,编写一个十进制转换为二进制的数制转换算法函数(要求利用栈来实现),并验证其正确性。
实现代码

void conveshen(SqStack *S) {
	ElemType n,h; 
	int m=0,k=0; 
	InitStack(S); 
	printf("Input element\n"); 
	scanf("%d",&n);  
	while(n) { 
		m++; 
    	Push(S,n%2); 
    	n=n/2; 
	} 
	while(k<m) {    
		k++; 
		Pop(S,&h); 
		printf("%d",h); 
	}
} 
int main() {    
	SqStack S; 
    conveshen(&S); 
	printf("\n");  
	return 0;
}

验证:

3、阅读并运行程序,并分析程序功能。

#include<stdio.h>
#include<malloc.h>
#include<string.h>
#define M 20
#define  elemtype  char
typedef struct
{
    elemtype stack[M];
    int top;
}
stacknode;
void init(stacknode *st);
void push(stacknode *st,elemtype x);
void pop(stacknode *st);

void init(stacknode *st)
{
    st->top=0;
}

void push(stacknode *st,elemtype x)
{
    if(st->top==M)
        printf("the stack is overflow!\n");
    else
    {
        st->top=st->top+1;
        st->stack[st->top]=x;
    }
}

void pop(stacknode *st)
{
if(st->top>0)  st->top--;
    else  printf(“Stack is Empty!\n”);
}

int main()
{
    char s[M];
    int i;
    stacknode *sp;
    printf("create a empty stack!\n");
    sp= (stacknode*)malloc(sizeof(stacknode));
    init(sp);
    printf("input a expression:\n");
    gets(s);
    for(i=0;i<strlen(s);i++)
    {
        if(s[i]=='(')
            push(sp,s[i]);
        if(s[i]==')')
            pop(sp);
    }
    if(sp->top==0)
        printf("'('match')'!\n");
    else
        printf("'('not match')'!\n");
    return 0;
}

输入:2+((c-d)6-(f-7)a)/6
运行结果:

输入:a-((c-d)*6-(s/3-x)/2
运行结果:

程序的基本功能:
判断多项式的左右括号是否配对。

四、实验小结
理解了栈、队列的概念,基本熟悉了入栈、出栈、入队、出队的操作,掌握了循环队列的特点及其操作,对程序代码的实现有了一个更为全面深刻的认识。

posted @ 2020-10-20 10:35  御清绝S  阅读(168)  评论(0)    收藏  举报