数据结构-栈和队列
四、栈的实现和应用
1、采用书上第 46 页定义的栈的顺序存储表示,编程实现栈的下列基本操作。
(1)初始化顺序栈 (2)创建顺序栈 (3)判断栈空 (4)输出顺序栈(5)取栈顶元素 (6)入栈 (7)出栈
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
typedef int Status;
typedef int SElemType;
//存储空间初始分配量
//存储空间分配增量
typedef struct{
SElemType *base;//在栈构造之前和销毁之后,base的值为NULL
SElemType *top;//栈顶指针
int stacksize;//当前已分配的存储空间,以元素为单位
}SqStack;
Status InitStack(SqStack &S){
//构造一个空栈S
S.base =(SElemType*)malloc(STACK_INIT_SIZE* sizeof(SElemType));
if(!S.base)exit(OVERFLOW);//存储分配失败
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
return OK;
}//initStack
Status StackEmpty(SqStack &S){
if(S.top==S.base)
return TRUE;
else
return FALSE;
}//StackEmpty
Status GetTop(SqStack &S, SElemType &e){
//若栈不空,则用e返回s的栈顶元素,并返回OK:否则返回ERROR
if(S.top ==S.base) return ERROR;
else e=*S.top;
return OK;
}//GetTop
Status Push(SqStack &S, SElemType e){
//插入元素e为新的栈顶元素
if(S.top-S.base >=S.stacksize){//栈满,追加存储空间
S.base = (SElemType* )realloc(S.base,(S.stacksize + STACKINCREMENT)* sizeof(SElemType));
if (!S.base) exit(OVERFLOW);//存储分配失败
S.top=S.base + S.stacksize;
S.stacksize+=STACKINCREMENT;
}
S.top++;
*S.top=e;
S.stacksize++;
return OK;
}//Push;
Status Pop(SqStack &S,SElemType &e){
//若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
if(S.top==S.base) return ERROR;
else{
e=*S.top;
S.top--;
S.stacksize--;
return OK;
}
}//Pop
Status Stackoutput(SqStack &S){
//若栈不空,则从栈顶到栈底依次输出数据元素,并返回OK;否则返回ERROR
SElemType *p;
if(S.top==S.base)return ERROR;
p=S.top;
while(p!=S.base){
printf("%d ",*p);
p--;
}
printf("\n");
return OK;
}//Stackoutput
Status StackTraverse(SqStack &S){
//若栈不空,则从栈底到栈顶依次输出数据元素,并返回OK;否则返回ERROR
SElemType *p;
if(S.top==S.base)return ERROR;
p=S.base+1;
while(p!=S.top+1){
printf("%d ",*p);
p++;
}
printf("\n");
return OK;
}//StackTraverse
int main(void){
int i,n,k,h,a,b;
SqStack S;
printf("创建一个空栈!\n");
InitStack(S);
printf("判断栈是否为空!\n");
printf("StackEmpty(S)=%d\n",StackEmpty(S));
printf("创建栈的元素个数:\n");
scanf("%d",&n);
printf("输入%d个入栈元素的值:\n",n);
for(i=0;i<n;i++){
scanf("%d",&k);
Push(S,k);
}
printf("逆序输出顺序栈元素值:\n");
Stackoutput(S);
printf("输出顺序栈元素值:\n");
StackTraverse(S);
printf("输入入栈元素值:");
scanf("%d",&h);
Push(S,h);
printf("输出入栈后的顺序栈元素值:\n");
StackTraverse(S);
Pop(S,a);
printf("输出第1个出栈元素值:%d\n",a);
Pop(S,a);
printf("输出第2个出栈元素值:%d\n",a);
printf("输出两次出栈后顺序栈元素值:");
StackTraverse(S);
GetTop(S,b);
printf("输出栈顶元素值:%d\n",b);
return 0;
}
2、采用栈的顺序存储表示,编程实现表达式中圆括号“( )”和方括号“[ ]”匹配的检验。
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
typedef int Status;
typedef char SElemType;
//存储空间初始分配量
//存储空间分配增量
typedef struct{
SElemType *base;//在栈构造之前和销毁之后,base的值为NULL
SElemType *top;//栈顶指针
int stacksize;//当前已分配的存储空间,以元素为单位
}SqStack;
Status InitStack(SqStack &S){
//构造一个空栈S
S.base =(SElemType*)malloc(STACK_INIT_SIZE* sizeof(SElemType));
if(!S.base)exit(OVERFLOW);//存储分配失败
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
return OK;
}//initStack
Status StackEmpty(SqStack &S){
if(S.top==S.base)
return TRUE;
else
return FALSE;
}//StackEmpty
Status GetTop(SqStack &S, SElemType &e){
//若栈不空,则用e返回s的栈顶元素,并返回OK:否则返回ERROR
if(S.top ==S.base) return ERROR;
else e=*S.top;
return OK;
}//GetTop
Status Push(SqStack &S, SElemType e){
//插入元素e为新的栈顶元素
if(S.top-S.base >=S.stacksize){//栈满,追加存储空间
S.base = (SElemType* )realloc(S.base,(S.stacksize + STACKINCREMENT)* sizeof(SElemType));
if (!S.base) exit(OVERFLOW);//存储分配失败
S.top=S.base + S.stacksize;
S.stacksize+=STACKINCREMENT;
}
S.top++;
*S.top=e;
S.stacksize++;
return OK;
}//Push;
Status Pop(SqStack &S,SElemType &e){
//若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
if(S.top==S.base) return ERROR;
else{
e=*S.top;
S.top--;
S.stacksize--;
return OK;
}
}//Pop
Status Correct(SElemType str[]){
//使用运算符栈S,当遇到'('、'['时进栈,遇到')'、']'出栈并判断出栈元素是否为相应的符号,若是则继续下一个,否则算法结束
SqStack S;
InitStack(S);//构造空栈
int i,state=1;
SElemType e;
for(i=0;str[i]!='\0';i++){
switch(str[i])
{
case '(':Push(S,str[i]);state++;break;
case '[':Push(S,str[i]);state++;break;
case ')':if(*S.top=='('){
Pop(S,e);
state--;
}
break;
case ']':if(*S.top=='['){
Pop(S,e);
state--;
}
break;
}
if(!state)break;
}
if(StackEmpty(S)&&state==1)
return OK;
else
return ERROR;
}//Correct
int main(void){
SElemType str[100];
printf("请输入带括号的表达式:\n");
scanf("%s",str);
if(Correct(str)==OK)
printf("括号匹配正确!\n");
else
printf("括号匹配不正确!\n");
return 0;
}
五、队列的存储表示和实现
1、采用书上第 61 页定义的队列的链式存储结构,编程实现队列的下列基本操作。
(1)构造空队列 (2)销毁队列 (3)清空队列 (4)判断队列是否为空 (5)求队列长度 (6)取队头元素 (7)插入队尾元素 (8)删除队头元素 (9)输出队列元素
//队列的链式表示
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define Status int
typedef int QElemType;
typedef struct QNode{
QElemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct{
QueuePtr front;//队头指针
QueuePtr rear;//队尾指针
}LinkQueue;
Status InitQueue(LinkQueue &Q){
//构造一个空队列
Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
if(!Q.front) exit(OVERFLOW);
Q.front->next=NULL;
return OK;
}
Status DestroyQueue(LinkQueue &Q){
//销毁队列Q
while(Q.front){
Q.rear=Q.front->next;
free(Q.front);
Q.front=Q.rear;
}
return OK;
}
Status ClearQueue(LinkQueue &Q){
//将Q清为空队列
QueuePtr p,q;
if(!Q.front) exit(OVERFLOW);
p=Q.front->next;
Q.front->next=NULL;
Q.rear=Q.front;
while(p)
{
q=p;
p=p->next;
free(q);
}
return OK;
}
Status QueueEmpty(LinkQueue Q){
//若队列Q为空队列,则返回TRUE,否则返回FALSE
if(Q.front==Q.rear)
return TRUE;
else
return FALSE;
}
int QueueLength(LinkQueue Q){
//返回Q的元素个数,即队列的长度
QueuePtr p;
int n=0;
p=Q.front;
while(Q.rear!=p)
{
n++;
p=p->next;
}
return n;
}
Status GetHead(LinkQueue Q,QElemType &e){
//若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR
QueuePtr p;
if(Q.front==Q.rear) return ERROR;
p=Q.front->next;
e=p->data;
return OK;
}
Status EnQueue(LinkQueue &Q,QElemType e){
//插入元素e为Q的新的队尾元素
QueuePtr p=(QueuePtr)malloc(sizeof(QNode));
if(!p) exit(OVERFLOW);//存储分配失败
p->data=e;
p->next=NULL;
Q.rear->next=p;
Q.rear=p;
return OK;
}
Status DeQueue(LinkQueue &Q,QElemType &e){
//若队列不空,则删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR
if(Q.front==Q.rear) return ERROR;
QueuePtr p=Q.front->next;
e=p->data;
Q.front->next=p->next;
if(Q.rear==p) Q.rear=Q.front;
free(p);
return OK;
}
Status QueueTraverse(LinkQueue &Q){
//从队头到队尾依次输出队列元素的值
QueuePtr p=Q.front->next;
if(p==NULL)return ERROR;
while(p)
{
printf("%d ",p->data);
p=p->next;
}
printf("\n");
return OK;
}
int main(void)
{
int i,n;
QElemType k,h,a,f;
LinkQueue Q;
printf("创建一个空队列!\n");
InitQueue(Q);
printf("判断队列是否为空!\n");
printf("QueueEmpty(Q)=%d\n",QueueEmpty(Q));
printf("创建队列的元素个数:\n");
scanf("%d", &n);
printf("输入%d个插入队列的元素的值:\n",n);
for(i=0;i<n;i++)
{
scanf("%d", &k);
EnQueue(Q, k);
}
printf("输出队列元素的个数:%d\n",QueueLength(Q));
printf("输出队列元素的值:\n");
QueueTraverse(Q);
printf("输入插入队列的元素的值:");
scanf("%d", &h);
EnQueue(Q, h);
printf("输出插入一个队列元素后队列元素的值:\n");
QueueTraverse(Q);
DeQueue(Q, a);
printf("输出第1个删除的队头元素的值:%d\n", a);
DeQueue(Q, a);
printf("输出第2个删除的队头元素的值:%d\n", a);
printf("输出两次删除队头元素后队列的元素值:");
QueueTraverse(Q);
GetHead(Q, f);
printf("输出队头元素的值:%d\n",f);
printf("输出队列元素的个数:%d\n",QueueLength(Q));
printf("将Q清为空队列!\n");
ClearQueue(Q);
printf("输出队列元素的个数:%d\n",QueueLength(Q));
printf("判断队列是否为空!\n");
printf("QueueEmpty(Q)=%d\n",QueueEmpty(Q));
return 0;
}
2、采用书上第 64 页定义的队列的顺序存储结构,编程实现循环队列的下列基本操作。
(1)构造空队列 (2)清空队列 (3)判断队列是否为空 (4)求队列长度 (5)取队头元素 (6)插入队尾元素 (7)删除队头元素 (8)输出队列元素
//队列的顺序表示:循环队列
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define MAXQSIZE 100//最大队列长度
typedef int Status;
typedef int QElemType;
typedef struct {
QElemType *base;//初始化的动态分配存储空间
int front;//头指针,若队列不空,指向队列头元素
int rear;//尾指针,若队列不空,指向队列尾元素的下一个位置
}SqQueue;
Status InitQueue(SqQueue &Q){
//构造一个空队列
Q.base=(QElemType *)malloc(MAXQSIZE*sizeof(QElemType));
if(!Q.base) exit(OVERFLOW);
Q.front=Q.rear=0;
return OK;
}
Status CLearQueue(SqQueue &Q)
{
//将Q清为空队列
if(!Q.base) exit(OVERFLOW);
Q.front=Q.rear=0;
return OK;
}
Status QueueEmpty(SqQueue Q)
{
//若队列Q为空队列,则返回TRUE,否则返回FALSE
if(Q.rear==Q.front) return TRUE;
else return FALSE;
}
int QueueLength(SqQueue Q){
//返回Q的元素个数,即队列的长度
return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;
}
Status GetHead(SqQueue Q,QElemType &e){
//若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR
if(Q.front==Q.rear)return ERROR;
e=Q.front;
return OK;
}
Status EnQueue(SqQueue &Q,QElemType e){
//插入元素e为新的队尾元素
if((Q.rear+1)%MAXQSIZE==Q.front) return ERROR;//队列满
Q.base[Q.rear]=e;
Q.rear=(Q.rear+1)%MAXQSIZE;
return OK;
}
Status DeQueue(SqQueue &Q,QElemType &e){
///若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR
if(Q.front == Q.rear)
return ERROR;
e = Q.base[Q.front];
Q.front = (Q.front + 1) % MAXQSIZE;
return OK;
}
Status QueueTraverse(SqQueue &Q){
int i;
if(Q.front==Q.rear) return ERROR;
i = Q.front;
while(i != Q.rear){
printf("%d ",Q.base[i]);
i = (i + 1) % MAXQSIZE;
}
printf("\n");
return OK;
}
int main(void)
{
int i,n;
QElemType k,h,a,f;
SqQueue Q;
printf("创建一个空队列!\n");
InitQueue(Q);
printf("判断队列是否为空!\n");
printf("QueueEmpty(Q)=%d\n",QueueEmpty(Q));
printf("创建队列的元素个数:\n");
scanf("%d", &n);
printf("输入%d个插入队列的元素的值:\n",n);
for(i=0;i<n;i++)
{
scanf("%d", &k);
EnQueue(Q, k);
}
printf("输出队列元素的个数:%d\n",QueueLength(Q));
printf("输出队列元素的值:\n");
QueueTraverse(Q);
printf("输入插入队列的元素的值:");
scanf("%d", &h);
EnQueue(Q, h);
printf("输出插入一个队列元素后队列元素的值:\n");
QueueTraverse(Q);
DeQueue(Q, a);
printf("输出第1个删除的队头元素的值:%d\n", a);
DeQueue(Q, a);
printf("输出第2个删除的队头元素的值:%d\n", a);
printf("输出两次删除队头元素后队列的元素值:");
QueueTraverse(Q);
GetHead(Q, f);
printf("输出队头元素的值:%d\n",f);
printf("输出队列元素的个数:%d\n",QueueLength(Q));
printf("将Q清为空队列!\n");
CLearQueue(Q);
printf("输出队列元素的个数:%d\n",QueueLength(Q));
printf("判断队列是否为空!\n");
printf("QueueEmpty(Q)=%d\n",QueueEmpty(Q));
return 0;
}
1万+

被折叠的 条评论
为什么被折叠?



