栈和队列的定义和特点
- 栈和队列是限定插入和删除只能在表的“端点”进行的线性表。
- 栈:插入和删除只能在表尾进行,特点:先进后出。
- 队列:插入在表尾插入,删除在表头删除。特点:先进先出。
- 栈是一个特殊的线性表,是限定尽在一端(通常是表尾)进行插入和删除操作的线性表。
- 又称后进先出的线性表,简称LIFO(Last In First Out)结构。
- 表尾称为栈顶top,表头称为栈底base。
- 在栈中插入元素的操作,插入到栈顶(表尾),叫入栈(压栈)。从栈顶删除一个元素叫出栈(弹栈 )。
栈
栈的抽象数据类型的定义
ADT Stack{
数据对象:D={ai|ai∈Elemset,i=1,2,...n,n≥0}
数据关系:{<ai-1,ai>|ai-1,ai∈D,i=2,...n,n≥0}
数据操作:入栈、出栈、求栈顶元素等
//———————————————————这是一条分割线———————————————————————//
InitStack(&S)//操作结果,构造一个空栈S。
DestoryStack(&S) //销毁栈操作
初始条件:栈S已经存在
操作结果:栈S被销毁
StackEmpty(S) //判断栈S是否为空
初始条件:栈S已经存在
操作结果:如果为空,返回true;反之返回False。
StackLength(S)//求解栈的长度
初始条件:栈已经存在
操作结果:返回S的元素个数,即栈的长度
GetTop(S,&e)//获取栈顶元素
初始条件:S已经存在
操作结构:用e返回S的栈顶元素
ClearStack (&S) //清空一个栈S
初始条件:S已经存在
操作结果:获得一个空栈
Push(&S,e)
初始条件:栈S已经存在。
操作结果:插入元素e为新的栈顶元素
Pop(S,&e)
初始条件:栈S已经存在。
操作结果:获取栈顶元素并用e返回。
}ADT Stack
顺序栈的表示和实现
- 设置top指针指向栈顶元素,另设base指针指向栈底元素。
- 通常情况下,为了方便操作,让top指针指向栈顶元素之上下表地址,如图所示。
- 使用stacksize表示栈可使用的最大容量。
- 栈空标志,base==top
- 栈满标志:top-base=stacksize,栈满可以出栈;栈满不可以入栈,会导致溢栈;
- 溢栈分文两种:
上溢:栈满还要压入元素;(是一种错误类型,使问题的处理无法进行)
下溢:栈空还要弹出元素(是一种结束条件,即问题处理结束)
顺序栈的定义
#define Maxsize 100
typedef struct SqStack
{
SElemtype *base;//栈底指针
SElemType *top; //栈顶指针
int Stacksize;//栈的最大可使用容量
}
顺序栈上的操作
-
顺序栈的初始化
Status InitStack(Sqstack &S){ S.base=new SElemType[MAXSIZE];//或者S.base=(SElemType*)malloc(MAXSIZE*sizeof(SElemtype)); if(!S.base) exit(OVERFLOW); S.top=S.base; Stacksize=MAXSIZE; return OK; }
-
判断顺序栈是否为空
Status StackEmpty(Sqstack S) { if(S.base==S.top) return TRUE; else return FALSE; }
-
求顺序栈的长度
int StackLength(S,int &e) { e=S.top-S.base; return e; }
-
清空顺序栈
Status ClearStack (SqStack &S) { if(S.base) else S.top=S.base; return OK; }
-
销毁顺序栈
Status DestoryStack (SqStack S) { if(S.base) { delete S.base; S.stackSize=0; S.base=S.top=NULL; } return OK; }
-
顺序栈的入栈
Status Push (SqStack &S,SElemType e) { if(S.top-S.bazs==Stacksize) //栈满 return ERROR; else *S.top=e; S.top++; return OK; }
-
顺序栈的出栈
Status Push (SqStack &S,SElemType &e) { if(!S.base==S.top) { --S.top; e=*S.top; } else return ERROR; return OK; }
链栈的表示和实现
链栈的定义
-
链栈是运算受限的单链表,只能在链表的头部进行操作。
#define Maxsize 100 typedef struct StackNode { SElemType data;//数据域 struct StackNode *next; }StackNode,*LinkStack; LinkStack S;
注意:
- 链栈当中指针方向和单链表的指针方向相反。
- 头指针指向栈顶
- 链栈中没有头结点。
- 基本不存在栈满的情况。
- 空栈相当于头指针指向空。
- 插入和删除只在栈顶进行。
链栈上的操作
-
链栈的初始化
Void InitStack(Linkstack &S) { S=null; return OK; }
-
判断链栈是否为空
Void LinkStackEmpty(Linkstack &S) { if(S=null)return true; else return False; }
-
链栈的入栈
Status Push(Linkstack &S,LinkNode e) { p=new StackNode; p->data=e; P->next=S; S=p return ok ; }
-
链栈的出栈
Status Pop(Linkstack &S,LinkNode &e) { p=new StackNode; if(S=NULL)return ERROR; e=S->data; //出栈的元素值保存在e中 p=S: S=S->next; delete p; return OK; }
-
取链栈栈顶元素
SElemType GetTop(Linkstack S) { if(S!=NULL) return S->data; }
队列
- 队列是一个特殊的线性表,是限定在表尾进行插入,在表头进行删除。
- 又称先进先出的线性表,简称FIFO(First In First Out)结构。
- 插入元素称为入队,删除元素称为出队。
- 队列的存储结构称为链队或顺序队。(常用循环顺序队)
队列的抽象数据类型定义
ADT Queue{
数据对象:D={ai|ai∈Elemset,i=1,2,...n,n≥0}
数据关系:{<ai-1,ai>|ai-1,ai∈D,i=2,...n,n≥0}
数据操作:入栈、出栈、求栈顶元素等
//———————————————————这是一条分割线———————————————————————//
InitQueue(&Q)//操作结果,构造一个空队列Q。
DestoryQueue(&Q) //销毁队列Q操作
初始条件:队列Q已经存在
操作结果:队列Q被销毁
QueueEmpty(Q) //判断队列Q是否为空
初始条件:队列Q已经存在
操作结果:如果为空,返回true;反之返回False。
QueueLength(Q)//求解队列Q的长度
初始条件:队列Q已经存在
操作结果:返回队列Q的元素个数,即队列Q的长度
GetHead(Q,&e)//获取栈顶元素
初始条件:队列Q已经存在
操作结构:用e返回队列Q的队头元素
ClearQueue (&Q) //清空一个队列Q
初始条件:队列Q已经存在
操作结果:获得一个空栈
EnQueue(&Q,e)
初始条件:队列Q已经存在。
操作结果:插入元素e为新的队尾元素
DeQueue(Q,&e)
初始条件:队列Q已经存在。
操作结果:删除对头元素并用e返回。
}ADT Queue
顺序队列的表示和实现
顺序队列的定义
#define MAXSIZE 100
Typedef struct{
QElemType *base;
int front ;//头指针
int rear;//尾指针,表示下表,并非真的指针
}SqQueue;
顺序队列上的操作
-
顺序循环栈的初始化
Status InitQueue(SqQueue &Q){ Q.base=new QElemType[MAXQSIZE];//或者Q.base=(QElemType*)malloc(MAXQSIZE*sizeof(QElemtype)); if(!Q.base) exit(OVERFLOW); Q.front=Q.near=0; return OK; }
-
求循环顺序队列的长度
int QueueLength(Q,int &e) { e=(Q.rear-Q.front+MAXQSIZE)%MAXQSIZE; return e; }
-
顺序队列的出队
Status DeQueue (SqQueue &Q,QElemType &e) { if(Q.rear=Q.front)//队空 return ERROR; e=Q.base[Q.front];//队头删除元素值 Q.front=(Q.front+1)%MAXQSIZE;//头指针加1 return OK; }
-
顺序队列的入队
Status 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; //队尾指针加1 return OK; }
-
取队头元素
QElemType GetHead(SqQueue Q,QElemType e) { if(Q.front=Q.rear) //队空 return ERROR; return Q.base[Q.front] //返回指针元素,队头指针不变 }
链式队列的表示和实现
链式队列的定义
//----------定义结点-------------//
#define MAXSIZE 100
Typedef 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)); Q.front->next=NULL; return OK; }
-
链队列的销毁
Status DestoryQueue(LinkQueue &Q) { while(!Q.front) { p=Q.front->next; //指向下一结点 free (Q.front); Q.front=p; } return OK; }
-
链队列的入队
Status EnQueue(LinkQueue &Q,QElemtype e)
{
p=(QueuePtr)malloc(sizeof(Qnode));
if(!p) exit(OVERFLLLOW);
p->data=e;
p->next=NULL;
Q.rear->next =p;
Q.rear=p;
return OK;
}
-
链队列的出队
Status DeQueue(LinkQueue &Q,QElemtype &e) { if(Q.front=Q.rear)//队空 return error; p=Q.front->next; e=p->data; Q.front->next=p->next; if(Q.rear==p) //删除为尾结点,需要修改尾指针 Q.rear=Q.front; delete p; return OK; }
-
链队列的队头
-
Status GetHead(LinkQueue Q,QElemtype &e) { if(Q.front=Q.rear)//队空 return error; e=Q.front->next->data; return e; }