3.1 顺序栈的建立
1.建立一个字符栈,从键盘输入若干个字符,以回车键结束,实现元素入栈操作;然后依次输出栈中的字符元素,实现元素出栈操作
2.实验要求和说明
参考程序中,由InitStack_Seq函数分配一个指定大小的字符数组空间,在分配成功地情况下,从键盘输入若干个字符,实现进栈操作。然后依次输出栈中元素的值,其输出顺序恰与输出顺序相反。注意入栈,出栈时栈顶指针TOP的不同变化及栈空的判断条件。建立一个头文件SeqStack.h,包含顺序栈的定义、初始化等。
3.参考程序
// 头文件SeqStack.h
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
//#include <string.h>
#define STACK_INIT_SIZE 50 // 存储空间初绐分配量
#define STACKINCREMENT 50 // 存储空间分配增量
#define OK 1
#define ERROR -1
#define OVERFLOW 0
typedef struct SeqStack
{ // 顺序栈类型定义
int MAXSIZE; // 栈中最大元素的个数(即栈空间的大小)
int top; // 栈顶指针
char *selem;
}SeqStack,*PSeqStack;
//typedef struct SeqStack *PSeqStack;
int InitStack_Seq(PSeqStack S) // 初始化顺序栈,见图3-11
{
S->selem = (char*)malloc(STACK_INIT_SIZE*sizeof(char));
if(!(S->selem))
exit(OVERFLOW);
S->top=-1;
S->MAXSIZE=STACK_INIT_SIZE;
return OK;
}
int IsEmptyStack_Seq(PSeqStack S)
{// 判栈是否为空
return( S->top == -1 ? OK : ERROR);
}
int IsFullStack_Seq(PSeqStack S)
{// 判栈是否满
return(S->top >= S->MAXSIZE-1 ? OK : ERROR);
}
int Push_Seq(PSeqStack S, char x)
{// 元素进栈
if(S->top >= S->MAXSIZE-1)
{
printf("Overflow!\n");
return ERROR;
}
S->top++;
S->selem[S->top] = x;
return OK;
}
int Pop_Seq(PSeqStack S, char *e)
{// 元素出栈
if(S->top == -1)
{
printf("Underflow!\n");
return ERROR;
}
*e = S->selem[S->top];
S->top--;
return OK;
}
int GetTop_Seq(PSeqStack S, char *e)
{// 取栈顶元素
if(S->top == -1)
{
printf("Underflow!\n");
return ERROR;
}
*e = S->selem[S->top];
return OK;
}
// 头文件SeqStack.h 结束
void main( )
{
SeqStack S_seq;
PSeqStack S;
char ch;
S = &S_seq;
InitStack_Seq(S);
printf("Input the datas to the stack, end Input \\n: ");
ch = getchar();
while( ch != '\n' && Push_Seq(S, ch))
{
ch = getchar();
}
printf("Output the datas in the stack: ");
for(;S->top != -1; S->top--) // 栈中元素出栈
printf("%c", S->selem[S->top]);
printf("\n");
3.思考题
(1)如果栈中的元素为结构类型,如何建立一个顺序栈?
typedef struct SeqStack
{
int MAXSIZE; //栈中最大元素的个数(即栈空间的大小)
int top; //栈顶指针
struct Student *selem; //结构体类型的元素指针
}SeqStack,*PSeqStack;
//定义一个Student结构体,只需要把结构体地址传给栈的selem就可以了,为了方便,用结构体数组来存储。
typedef struct Student
{
int id; //学号
char sex; //性别 F/M
char name[11]; //名字
}Student,*Stu;
int Push_Seq(PSeqStack S,Student x) { ......} //函数里边内容不变
int Pop_Seq(PSeqStack S,Student *e){......}
int GetTop_Seq(PSeqStack S,Student *e){......}
int main()
{
SeqStack S_seq;
PSeqStack S;
S = &S_seq; int i=-1,n;
InitStack_Seq(S);
struct Student stu[50];
do{
i++;
printf("请输入第%d个学生的信息 id sex name(0 0 0 结束):", i);
scanf ("%d %c %s",&stu[i].id, &stu[i].sex, stu[i].name);
}
while(stu[i].id != 0 && Push_Seq(S,stu[i]));
printf("Output the datas in the satck:");
for(;S->top != -1; S->top--)
{
*stu = S->selem[S->top];
printf("id: %d ,sex: %c ,name: %s \n",stu->id,stu->sex,stu->name);
}
printf("\n");
return 0;
}
(2)设计一个算法,利用栈的基本运算,返回指定顺序栈中的栈底元素。
int GetSelem_Seq(PSeqStack S,char *e)
{
//取栈底元素、若栈i非空,用变量*e返回栈顶元素
int i;
printf("top = %d\n",S->top);
if(S->top <= -1)
{
printf("The Stack is NULL!\n");
return ERROR;
}
else
*e = S->selem[0];
return OK;
}
3.2 顺序栈的共享共用
1.建立两个迎面增长的共享栈Stack0,Stack1,栈元素为char类型。分别完成建栈、取栈顶元素及求栈的长度(栈元素的个数)操作。建栈时,支持字符元素连续输入。
2.实验要求及说明
顺序栈共用,即使多个顺序栈共用一个足够大的数组空间,并利用栈的动态特性使其存储空间互补。下面实现的两个顺序栈共用算法可以推广到多个共用栈。
参考程序中设置了一个结构类型:DseqStack,用于描述两个迎面增长的共享栈的状态。程序中利用整型变量i控制对不同栈的操作。注意两个共享栈Stack0,Stack1的栈底位置的不同和栈顶指针变化的差异。两个顺序栈共用结构示意图如图所示。
3.参考代码
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#define STACK_INIT_SIZE 10
#define OK 1
#define ERROR -1
#define OVERFLOW 0
typedef struct DSeqStack
{ // 共用栈的结构定义
char *selem[2]; // 两个栈的栈底指针
int top[2]; // 两个栈的栈顶指针
int MAXSIZE; // 共用栈的大小
}DSeqStack, *PDSeqStack;/
int InitStack_DSeq(PDSeqStack S)
{ // 初始化共享栈DSeq
// 分别设置 Stack0、Stack1 的栈底指针selem[0]、selem[1]
S->selem[0]=(char *)malloc(STACK_INIT_SIZE*sizeof(char));
if(!S->selem[0])
exit(OVERFLOW);
S->MAXSIZE = STACK_INIT_SIZE;
S->selem[1]= S->selem[0]+S->MAXSIZE-1; // 设置 Stack1 的栈底指针selem[1]//
S->top[0] = -1; // 栈 Stack0 的初始状态
S->top[1] = S->MAXSIZE; // 栈 Stack1 的初始状态///
return OK;
}
int CreateStack_DSeq(PDSeqStack S, int i)
{ // 建立顺序字符栈i
char ch;
if(i==0)
{ // 建立栈Stack0
while((ch = getchar())!='\n')
{
S->top[0]++;
if(S->top[0] >= S->top[1])
{
printf("The stack is full!\n");
exit(OVERFLOW);
}
else
S->selem[0][S->top[0]] = ch;//
}
}
if(i==1)
{ // 建立栈Stack1
while((ch = getchar())!='\n')
{
S->top[1]--;
if(S->top[1] <= S->top[0])
{
printf("The stack is full!\n");
exit(OVERFLOW);
}
else
S->selem[1][S->top[1]] = ch;//
}
}
return OK;
}
int GetTop_DSeq(PDSeqStack S, int i, char *e)
{ // 取栈顶元素。若栈 i 非空,用变量 *e 返回栈顶元素
if(i==0)
{
if(S->top[0] <= -1)//
{
printf("The stack%d is NULL!\n",i);
return ERROR;
}
else
*e = S->selem[0][S->top[0]];///
}
if(i==1)
{
if(S->top[1] >= S->MAXSIZE)///
{
printf("The stack%d is NULL!\n",i);
return ERROR;
}
else
*e = S->selem[1][S->top[1]];///
}
return OK;
}// end GetTop_DSeq
int GetDepth_DSeq(PDSeqStack S, int i)
{ // 求栈i中元素的个数。
int t,p1,p2;
p1 = S->top[0];//
p2 = S->top[1];//
if(i==0)
{
for(t=0; p1 >-1; t++,p1--);
}
if(i==1)
{
for(t=0; p2<S->MAXSIZE; t++,p2++);
}
return t;
}
void main( )
{
DSeqStack s;
PDSeqStack S;
int i,t,k;
char e;
S = &s;
InitStack_DSeq(S);
printf("Enter 0 for the left stack0 operation\n");
printf("Enter 1 for the right stack1 operation:");
for(;;)
{
printf("\n1: createstack, 2: gettop, 3: getlength. please enter k=");
scanf("%d",&k);
//fflush(stdin); // 清除回车键
switch(k)
{
case 1: printf("\n now begin CreateStack_DSeq: please Enter i=");
scanf("%d",&i);
fflush(stdin);
if(i==0)
{
printf("Input the datas of char to the stack 0: ");
CreateStack_DSeq(S,0);
}
if(i==1)
{
printf("Input the datas of char to the stack 1: ");
CreateStack_DSeq(S,1);
}
break;
case 2: printf("\n now begin GetTop of stack. please Enter i=");
scanf("%d",&i);
//fflush(stdin);
if(i==0)
{
if(GetTop_DSeq(S,0,&e))
printf("\nThe data on the top of the left stack0 is %c",e);
else
printf("The left stack0 is empty!\n");
}
if(i==1)
{
if(GetTop_DSeq(S,1,&e))
printf("\nThe data on the top of the left stack1 is %c",e);
else
printf("The left stack1 is empty!\n");
}
break;
case 3: printf("\n now begin GetDepth of stack. please Enter i=");
scanf("%d",&i);
//fflush(stdin);
if(i==0)
{
t=GetDepth_DSeq(S,0);
printf("the depth of the left stack0 is %d\n",t);
}
if(i==1)
{
t=GetDepth_DSeq(S,1);
printf("the depth of the right stack1 is %d\n",t);
}
break;
default: exit(0);
}//endswitch
}//endfor
}//endmain
4.思考题
(1)如何用函数实现栈中元素的出栈操作?试修改上述程序,对于一个非空栈,实现删除栈顶元素,并由变量e返回其值的算法
int DeleteTop_DSeq(PDSeqStack S,int i,char *e)
{
//取栈顶元素、若栈i非空,用变量*e返回栈顶元素
if(i==0)
{
if(S->top[0] <= -1)
{
printf("The stack%d is NULL!\n",i);
return ERROR;
}
else
*e = S->selem[0][S->top[0]];
S->top[0]--;
}
if(i==1)
{
if(S->top[i] >= S->MAXSIZE)
{
printf("The stack%d is NULL!\n");
return ERROR;
}
else
*e = S->selem[1][S->top[1]];
S->top[0]++;
}
return OK;
}//end DeleteTop_DSeq
Int main()
{
......
While ....
.......
case 4:printf("\n now begin DeleteTop of stack.please Enter i= ");
scanf("%d",&i);
//fflush(stdin);
if(i==0)
{
if(DeleteTop_DSeq(S,0,&e))
printf("\nThe data on the top of the left stack0 is %c",e);
else
printf("The left stack0 is empty!\n");
}
if(i==1)
{
if(DeleteTop_DSeq(S,1,&e))
printf("\nThe data on the top of the left stack1 is %c",e);
else
printf("The left stack1 is empty!\n");
}
break;
}
(2)在栈的操作中,栈满时仍进行入栈操作称为“上溢”,栈空时仍进行出栈操作称为“下溢”,试分析这两种溢出中的哪一种是正常现象?哪一种是错误状态。
栈溢出属于系统重大漏洞,这种漏洞将会产生相当严重网络安全事件。