栈和队列的定义和特点:
插入删除只能在表的 “端点” 进行的线性表
栈 后进先出(称作LIFO)
只能在队尾和队头插入删除
表尾成为栈顶Top,表头成为栈低Base
插入元素到栈顶(即表尾)的操作,成为入栈(PUSH)
从栈顶(即表尾)删除最后一个元素的操作,称为出栈(POP)
队列
只能删除第一个(队头)元素,在最后(队尾)插入
先进先出
栈(Stack)的表示和操作实现
空栈:base == top是栈空的标志
栈满:top - base == stacksize
栈满时的处理方法:
1.报错,返回操作系统
2.分配更大的空间,作为栈的存储空间,将原栈的内容移入新栈
上溢:栈满了,仍要存入
下溢:栈已经空了,仍要弹出元素
顺序栈的表示:
# define MAXSIZE 100
typedef struct{
SElemType *base;//栈低指针
SElemType *top;//栈顶指针
int stacksize;//栈可用最大容量
}SqStack;
1.初始化
top 指针和 base 指向统一位置 stacksize == 0
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;
S.stacksize = MAXSIZE;
return OK;
}
2.销毁
Status DestroyStack(SqStack &S)
{
if(S.base){
delete S.base;
S.stacksize = 0;
S.base = S.top = NULL;
}
return OK;
}
3.判断S是否为空
Status StackEmpty(SqStack S){
if (S.top == S.base)
return TRUE;
else
return FALSE;
}
4.栈的长度
int StackLength(SqStack S)
{
return S.top - S.base;
}
//
Status ClearStack(SqStack S){
if (S.base)
S.top = S.base;
return OK;
}
5.获取栈顶元素
6.清空操作
认为他是空就可以了
栈顶指向栈尾
Status ClearStack(SqStack S){
if(S.base)
S.top = S.base;
return OK;
}
7.入栈操作
判断是否栈满,若满则出错
Status Push(SqStack &S,SElemType e){
if(S.top - S.base == S.stacksize)//栈满
return ERROR;
*S.top = e;
S.top++; //*S.top++ = e;
}
8.出栈操作
Status Pop(SqStack &S,SElemType e)
{
if(S.top == S.base)
return REEOR;
S.top--;
e = *S.top;//两步合成一步e = *--S.top
}
9.
队列的顺序表示和操作实现(Queue)
类型定义
//队列
typedef struct{
QElemType *base;//初始化的分配内存空间
int front;//头指针 若队列不为空,指向队列头元素
int rear; //尾指针 若队列不为空,指向队列尾元素的下一位置
}SqQueue;
真溢出:front == 0,rear = MAXQSIZE 队列已经满了,无法在插入元素
假溢出:front != 0,rear = MAXQSIZE 队列不满,如上图
解决:1.移动位置:缺点浪费时间,将剩下所有元素都移动
2.引入循环队列
base[0]接在base[MAXQSIZE - 1]之后,若rear + 1 == M,则令rear=0 实现方法:利用模运算(% 取余)
相当于
那怎么判断是队空还是队满
解决方案:少用一个元素空间
1.队列的初始化
Status InitQueue(SqQueue &Q){
Q.base = new QElemType[MAXQSIZE] //分配数组空间
//Q.base = (QElemType*)malloc(MAXQSIZE*sizeof(QWElemType));
if (!Q.base)
{
exit(OVERFLOW);
}
Q.front = Q.rear = 0;//头指针尾指针为0,队列为空
return OK;
}
2、求队列的长度
两种情况
第一个:rear > front Queuelength = Q.rear - Q.front
第二个:rear < front Queuelength = (Q.rear - Q.front + MAXSIZE) % MAXSIZE 例:front = 4,rear = 1 length = (1-4+6)%6 = 3
int QueueLength(SqQueue Q){
return (Q.rear - Q.front + MAXSIZE) % MAXSIZE
}
3.入队算法
Status EnQueue(SqQueue &Q,QElemType e){
if ((Q.rear + 1 ) % MAXSIZE == Q.front )
return ERROR;//判断队列是否为满
Q.base[Q.rear ] == e;//新元素加入队尾
Q.rear = (Q.rear + 1) % MAXQSZIE//队尾指针+1
return OK;
}
4.出队
Status DeQueue(SqQueue &Q,QElemType e)
{
if (Q.front == Q.rear )
return ERROR;//队空
e = Q.base[Q.front ]//保存队头元素
Q.front = (Q.front + 1) % MAXQSIZE;
return OK;
}
5.取队头元素
SElemType GetHead(SqQueue Q){
if (Q.front == Q.rear )
return ERROR;//队列不为空
return Q.base[Q.front]//返回队头指针元素的值,队头指针不变
}
队列的链式表示和实现
若用户无法估计所用队列的长度,则宜采用链队列
1.链队列的类型定义
typedef struct Qnode{
QElemType data;
struct Qnode *next;
}QNode,*QuenePtr;(pointer)
typedef struct {
QuenePtr front;//队头指针
QUenePtr rear;//队尾指针
}LinkQueue;
链式队列运算指针变化状况 空队列
元素X入队
y入队
x出队
然后将x释放
2.链队列的初始化
Status InitQueue(LinkQueue &Q)
{
Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
Q.front->next = NULL;
return OK;
}
3.销毁链队列
Status DestryQueue(LinkQueue &Q){
while(Q.front )
{
p = Q.front->next;//先将下一节点存起来
free(Q.front);//释放结点
Q.front = p; //指向下一节点
}
}
4.将元素e入队
Status EnQueue(LinkQueue &Q,QElemType e){
p = (QueuePtr)malloc(sizeof(QNode));
p->data = e;
p->next = NULL;
Q.rear->next = p;
Q.rear = p;//更新尾指针
return OK;
}
5.链队列出列
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;
free(p);
return
}
6.求队头元素
Status GetHead (LinkQueue Q,QElemType &e){
if(Q.front==Q.rear)
return ERROR;
e=Q.front->next->data;
return OK;
}