第四次作业
这个作业属于哪个课程 | < https://edu.cnblogs.com/campus/qdu/DS2020/ > |
---|---|
这个作业要求在哪里 | < https://edu.cnblogs.com/campus/qdu/DS2020/homework/11296 > |
这个作业的目标 | <栈和队列> |
学号 | 2018204158 |
一、实验预习
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) {
S->base=(ElemType*)realloc( S->base,(S->stacksize+STACKINCREMENT)*sizeof(ElemType) );
S->top=S->base+S->stacksize;
S->stacksize+=STACKINCREMENT;
}
*S->top++=e;
return 1;
}/*Push*/
int Pop(SqStack *S,ElemType *e){
if (S->top!=S->base) {
*e=*--S->top;
return 1;
}
else
return 0;
}/*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?体现了栈的什么特性?
2、在第1题的程序中,编写一个十进制转换为二进制的数制转换算法函数(要求利用栈来实现),并验证其正确性。
#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)
{
S->base=(ElemType *)realloc(S->base,(S->stacksize+STACKINCREMENT)*sizeof(ElemType));
if(S->base==NULL)
{
return 0;
}
S->top=S->base+S->stacksize;
S->stacksize=S->stacksize+STACKINCREMENT;
}
*S->top=e;
S->top++;
return 1;
}/*Push*/
int Pop(SqStack *S,ElemType *e)
{
if(S->top==S->base)
{
return 0;
}
else
{
S->top--;
*e=*S->top;
return 1;
}
}/*Pop*/
int IsEmpty(SqStack *S)
{
if(S->top==S->base)
return 1;
else
return 0;
}
void Change(int n)
{
SqStack S;
int x;
InitStack(&S);
while(n>0)
{
x=n%2;
Push(&S,x);
n=n/2;
}
while(!IsEmpty(&S))
{
Pop(&S,&x);
printf("%d", x);
}
}
int main()
{
SqStack ss;
int n;
printf("请输入一个十进制数\n");
scanf("%d",&n);
printf("转换后变成的二进制数\n");
Change(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=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
运行结果:
程序的基本功能:判断输入的多项式中,左右括号是否配对。
4、设计算法,将一个表达式转换为后缀表达式,并按照后缀表达式进行计算,得出表达式得结果。
#include <stdio.h>
#include <stdlib.h>
#define STACK_INIT_SIZE 20
#define STACKINCREMENT 10
typedef char ElemType;
typedef struct{
ElemType *base;
ElemType *top;
int stackSize;
}sqStack;
InitStack(sqStack *s){
s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
if( !s->base )
exit(0);
s->top = s->base;
s->stackSize = STACK_INIT_SIZE;
}
Push(sqStack *s, ElemType e){
if( s->top - s->base >= s->stackSize )
{
s->base = (ElemType *)realloc(s->base, (s->stackSize + STACKINCREMENT) * sizeof(ElemType));
if( !s->base )
exit(0);
s->top = s->base + s->stackSize;
s->stackSize = s->stackSize + STACKINCREMENT;
}
*(s->top) = e;// 存放数据
s->top++;
}
Pop(sqStack *s, ElemType *e){
if( s->top == s->base )
return;
*e = *--(s->top);// 将栈顶元素弹出并修改栈顶指针
}
int StackLen(sqStack s){
return (s.top - s.base);
}
int main(){
sqStack s;
char c, e;
InitStack( &s );
printf("请输入中缀表达式,以#作为结束标志:");
scanf("%c", &c);
while( c != '#' ){
while( c>='0' && c<='9' ){
printf("%c", c);
scanf("%c", &c);
if( c<'0' || c>'9' ){
printf(" ");
}
}
if( ')' == c ){
Pop(&s, &e);
while( '(' != e ){
printf("%c ", e);
Pop(&s, &e);
}
}
else if( '+'==c || '-'==c ){
if( !StackLen(s) ){
Push(&s, c);
}
else{
do{
Pop(&s, &e);
if( '(' == e ){
Push(&s, e);
}
else{
printf("%c ", e);
}
}
while( StackLen(s) && '('!=e );
Push(&s, c);
}
}
else if( '*'==c || '/'==c || '('==c ){
Push(&s, c);
}
else if( '#'== c )
break;
}
else{
printf("\n出错:输入格式错误!\n");
return -1;
}
scanf("%c", &c);
}
while( StackLen(s) ){
Pop(&s, &e);
printf("%c ", e);
}
return 0;
}
5、假设以带头结点的循环链表表示队列,并且只设一个指针指向队尾结点(不设队头指针),试编写相应的置空队列、入队列、出队列的算法。
#include <stdio.h>
#include <stdlib.h>
#define ERROR 0
#define OK 1
#define OVERFLOW 0
typedef int qelemType;
typedef struct queue
{
qelemType data;
struct queue *next;
}queue,*linkqueue;
typedef struct
{
linkqueue rear;
int length;
}sqqueue;
void initQueue(sqqueue &queue)//置空队列
{
queue.rear=(linkqueue)malloc(sizeof(queue));
queue.rear->next=queue.rear;
}
int emptyQueue(sqqueue &queue)//判队列是否为空
{
if(queue.rear->next==queue.rear)
return OK;
else
return 0;
}
int enqueue(sqqueue &queue,qelemType e)
{
linkqueue p;
p=(linkqueue)malloc(sizeof(queue));
if(!p)
return OVERFLOW;
p->data=e;
p->next=queue.rear->next;
queue.rear->next=p;
queue.rear=p;
return OK;
}
int delqueue(sqqueue &queue,qelemType &e)
{
linkqueue p;
if(queue.rear->next==queue.rear)
return ERROR;//若队列为空返回0
p=queue.rear->next->next;//循环链表队列队尾指针下一结点的下一结点
e=p->data;
queue.rear->next->next=p->next;
free(p);
//delete(p);//free函数与delete函数均可使用
return OK;
}
int main()
{
sqqueue queue2;
qelemType num;
initQueue(queue2);
if(emptyQueue(queue2))
printf("该队列目前为空!\n");
else
printf("该队列不为空!\n");
for(int i=1;i<=10;i++)
if(enqueue(queue2,i))
printf("元素%d成功入列!\n",i);
printf("\n\n");
for(int j=1;j<=9;j++)
if(delqueue(queue2,num))
printf("元素%d成功出列!\n",num);
if(emptyQueue(queue2))
printf("该队列目前为空!\n");
else
printf("该队列不为空!\n");
return 0;
}