第三章 栈和队列
1. 栈的定义:限定仅在表尾进行插入和删除操作的线性表。
2. 栈的操作特性:后进先出
3. 栈的逻辑结构与线性表相同,仍为一对一关系
4. 栈的存储结构用顺序栈或链栈存储均可
5. 栈的顺序存储结构及表示
6. 顺序栈的基本操作实现:
顺序栈初始化:
Status InitStack( SqStack &S )
{ //构造一个空栈
S.base =new SElemType[MAXSIZE];
if( !S.base )
exit(OVERFLOW);
S.top = S.base;
S.stackSize = MAXSIZE;
return OK;
}
判断顺序栈是否为空
求顺序栈的长度
清空顺序栈
销毁顺序栈
入栈:
Status Push ( SqStack &S, SElemType e)
{ //插入元素e为新的栈顶元素
if ( S.top-S.base==S.stacksize )
return ERROR;
*S.top++ = e; // *S.top=e; S.top++;
return OK;
}
出栈:
Status Pop ( SqStack &S, SElemType & e)
{ //若栈不空,则删除S的栈顶元素,用e返回其值,
并返回OK;否则返回ERROR
if ( S.top == S.base ) return ERROR;
e=*--S.top; // --S.top; e=*S.top;
return OK;
}
取栈顶元素:
Status GetTop( SqStack S, SElemType &e)
{ // 若栈不空,则用e返回S的栈顶元素
if( S.top == S.base ) return ERROR;
e = *( S.top – 1 );
return OK;
}
7. 链栈的表示:运算是受限的单链表,只能在链表头部进行操作,故没有必要附加头结点。栈顶指针就是链表的头指针。
8. 链栈的基本操作实现:
入栈:
Status Push(LinkStack &S , SElemType e)
{
p=new StackNode;
if (!p) exit(OVERFLOW);
p->data=e;
p->next=S;
S=p;
return OK;
}
出栈:
Status Pop (LinkStack &S,SElemType &e)
{
if (S==NULL) return ERROR;
e = S-> data;
p = S;
S = S-> next;
delete p;
return OK;
}
9. 树、广义表具有递归特性。
10. 递归——>非递归
11. 队列的定义:只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
12. 队列的操作特性:先进先出
13. 队列的逻辑结构:与线性表相同,仍为一对一关系。
队列的存储结构:用顺序队列或链队列存储均可。
14. 队列的表示和实现:
链队列:采用链式存储结构的队列
顺序队列:采用顺序存储结构的队列
15. 链队的操作实际上是单链表的操作,只不过是删除在表头进行,插入在表尾进行(体现了先进先出)。
16. 队列的链式存储结构:
17. 链队的操作:
构造空队列
Status InitQueue (LinkQueue &Q)
{ // 构造一个空队列Q
Q.front = Q.rear = new QNode;
Q.front->next = NULL;
return OK;
}
销毁队列
Status DestroyQueue (LinkQueue &Q)
{//销毁队列Q
while (Q.front)
{
Q.rear = Q.front->next;
delete Q.front;
Q.front = Q.rear;
}
return OK;
}
入队
Status EnQueue (LinkQueue &Q, QElemType e)
{ //插入元素e为Q的新的队列尾元素
p =new QNode;
p->data = e;
p->next = NULL;
Q.rear->next = p; // 修改尾结点的指针
Q.rear = p; // 移动队尾指针
return OK;
}
出队
Status DeQueue (Queue &Q, QElemType &e)
{ // 若队列不空,则删除Q的队头元素,用e返回其值,
并返回OK;否则返回ERROR
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;
}
18. 队列的顺序存储结构
假溢出问题:
解决方案A:每出队一个元素,队列中所有元素前移。分析:时间花费太大。
解决方案B:队列空间循环使用——循环队列。
19. 循环队列中:
队头,队尾指针取值在0~Maxsize-1之间循环
队头指针表示真正的队头,队尾指针表示真正队尾的下一位置。
入队: sq[rear]=x; rear=(rear+1)% Maxsize;
出队: x=sq[front]; front=(front+1)% Maxsize;
初始化: front = rear = 0;
求循环队列的长度:(Q.rear - Q.front + Maxsize)% Maxsize;
队空的条件: front = = rear;
队满的条件: front = = (rear + 1) % Maxsize;
20. 循环队列:
循环队列的存储结构:
#define MAXQSIZE 100 //最大队列长度
typedef int QElemType;
typedef struct {
QElemType *base; //用于动态分配存储空间
int front; //队头索引
int rear; //队尾索引
}SqQueue;
循环队列初始化:
Status InitQueue (SqQueue &Q)
{//构造一个空队列
Q.base =new QElemType[MAXQSIZE];
if(!Q.base) exit(OVERFLOW);
Q.front=Q.rear=0;
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;
return OK;
}
出队:
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;
}
21.
22. 顺序栈
栈空条件是top==-1
栈满条件是top==maxsize-1