栈和队列
第三章 栈和队列
3.1 栈和队列的定义和特点
3.1.1 栈的定义和特点
表头 - 栈顶
表尾 - 栈底
只能从栈底进行插入和删除 后进先出LIFO
3.1.2 队列的定义和特点
队尾插入 队头删除
先进先出FIFO
3.2 案例
3.3 栈的表示和操作的实现
3.3.1 栈的类型定义
栈的两种表示方法:顺序栈和链栈。
3.3.2 顺序栈的表示和实现
顺序栈受最大空间限制
栈空标志base == top
栈满标志top - base == MAXSIZE
定义:
#define MAXSIZE = 100
typedef struct {
SElemType *base;
SElemType *top;
int stacksize;
} SqStack;
- 初始化
定义的top指向栈顶元素的上一个位置 栈空时top和base都指向栈底
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) { if(S.top - S.base == S.stacksize) return ERROR; *S.top++=e; // e压入栈顶 栈顶指针自加1 return OK; } -
出栈
Status Pop(SqStack &S, SElemType &e) { if(S.top == S.base) return ERROR; e = *--S.top; return OK; } -
取栈顶元素
SElemType GetTop(SqStack S) { if(S.top != S.base) return *(S.top - 1); // 注意栈顶指针不变 只返回栈顶元素的值 }
3.3.3 链栈的表示和实现
定义:
typedef struct StackNode{
ElemType data;
struct StackNode *next;
} StackNode, *LinkStack;
-
初始化
Status InitStack(LinkStack &S) { S = NULL; return OK; } -
入栈
不用判断栈是否满 因为链栈不会满
Status Push(LinkStack &S, SElemType e) {
p = new LinkNode;
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;
}
需要判断栈是否为空
-
取栈顶元素
SElemType GetTop(SqStack S) { if(S.top != S.base) return *(S.top - 1); }
3.4 栈与递归
3.4.1 递归解决的问题
分治法:
(1)有明确的递归出口(结束条件)
(2)问题可以转化为一个新问题,与原问题解法类似,而且处理对象更小且变化有规律
void p(参数表) {
if(递归条件不成立) p(较小的参数表);
}
3.5 队列的表示和操作的实现
3.5.1
3.5.2 循环队列
初始化:front = rear = 0
定义头指针指向队头 尾指针指向队尾元素的下一个位置
循环队列:解决数组越界造成的假溢出问题
循环队列判断队满还是队空:
-
少用一个元素空间
队满:
Q.front == Q.rear队空:
(Q.rear + 1) % MAXQSIZE == Q.front -
另设标志位
循环队列操作的实现:
-
初始化
Status InitQueue(SqQueue &Q) { Q.base = new QElemType[MAXSIZE]; if(!Q.base) exit(OVERFLOW); Q.front = Q.rea = 0; return OK; } -
求队列长度
int QueueLength(SqQueue Q) { return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE; } -
入队
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, QElemTypr &e) { if(Q.front == Q.rear) return ERROR; e = Q.base[Q.front]; Q.front = (Q.front + 1) % MAXQSIZE; return OK; } -
取队头元素
SElemType GetHead(SqQueue Q) { if(Q.front != Q.rear) return Q.base[Q.front]; }设定循环队列时 必须为其设一个最大队列长度 如果无法预估 则应该采用链队
3.5.3 链队 队列的链式表示与实现
设置头结点;头指针始终指向头结点
-
初始化
Status InitQueue(LinkQueue &Q) { Q.front = Q.rear = new QNode; Q.front -> next = NULL; // 头结点指针域置空 return OK; } -
入队
Status EnQueue(LinkQueue &Q, QElemType e) { p = new QNode; p -> data = e; p -> next = NULL; 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; } -
取队首元素
SElemType GetHead(LinkQueue Q) { if(Q.front != Q.rear) return Q.front -> next -> data; }
浙公网安备 33010602011771号