栈和队列
栈(Stack)
定义与特点
栈是一种特殊的线性表,只能从一端进行插入和删除------>后进后出 LIFO结构
表尾(an) 称为栈顶Top 表头(a1)称为栈底Base
插入元素到栈顶 的操作称为入栈
删除栈顶 最后一个元素的操作称为出栈
抽象类型定义
ADT Stack{
数据对象:
D = {ai|ai∈ElemSet,i=1,2,3,...n,n≥0}
数据关系:
R1 = {<ai-1,ai>|ai-1,ai∈D,i=2...,n}
约定an端为栈顶,a1端为栈底
基本操作:
初始化,进栈,出栈,取栈元素等
}ADT Stack
基础操作
InitStack(&S):初始化一个空栈S。
StackEmpty(S):判断一个栈是否为空
StackLength(S):求栈长度
Push(&S, x):进栈------栈的插入操作
Pop(&S, &x):出栈------栈的删除操作
GetTop(S, &e):读栈顶元素
ClearStack(&S):栈置空
DestroyStack(&S):栈销毁
顺序栈
为方便top指针指向栈顶元素之上的下标地址
stacksize ------> 栈可使用的最大容量
空栈的标志:base == top
栈满的标志: top - base == stacksize
------------ 元素个数计算即top - base
上溢:栈满进行插入 下溢:栈空继续弹出
顺序栈的数据类型定义
#define MAXSIZE 100
typedef struct{
SElemType *base;//栈底指针
SElemType *top;//栈顶指针
int stacksize;//栈可用最大容量
}SqStack;
顺序栈的初始化
Status lnitStack(SqStack &S)
{
S.base = new SElemType[MAXSIZE];
if(!S.base) exit (OVERFLOW);//存储分配成功
S.top = S.base;
S.stacksize = MAXSIZE;
return OK;
}
判断顺序栈是否为空
Status StackEmpty(SqStack S)
{
if(S.top == S.base)
return TURE;
else
return FALSE;
}
求顺序栈的长度
int StackLength(SqStack S)
{
return S.top - S.base;
}
清空顺序栈
Status ClearStack(SqStack S){
if(S.base) S.top = S.base;
return OK;
}
销毁顺序栈
Status DestroyStack(SqStack &S){
if(S.base){
delete S.base;
S.stacksize == 0;
S.base = S.top = NULL;
}
return OK;
}
顺序栈的入栈
1.判断栈是否满,若满则出差(上溢)
2.元素e压入栈顶
3.栈顶指针加1
Status Push(SqStack &S, SElemType e){
if(S.top - S.base == S.stacksize)
return ERROR;
*S.top++ = e; //先e赋值给*S.top再移动指针++
return OK;
}
}
顺序栈的出栈
1.判断栈是否为空,空则出错(下溢)
2.获取栈顶元素e
3.栈顶指针-1
Status Pop(SqStack &S, SElemType &e){
if(S.top == S.base)
return ERROP;
e = *--S.top;
return OK;
}
链栈
链栈指针方向与链表方向相反
· 链表的头指针就是栈顶
· 不需要头节点
· 基本不存在栈满的情况
· 空栈相当于头指针指向空
· 插入和删除仅在栈顶处执行
数据类型定义
typedef struct StackNode{
SElemType date;
struct StackNode *next;
}StackNode,*LinkStack;
LinkStack S;
初始化
void lnitStack(LinkStack &S){
S = NULL;
return OK;
}
判断链栈是否为空
Status StackEmpty(LinkStack S){
if(S == NULL) return TURE;
else return FlASE;
}
链栈入栈
Status Push(LinkStac &S,SElemType e){
p = new StackNode;
p -> date = e;
P -> next = S;
S = p;
return OK;
}
链栈出栈
Status Pop(LinkStac &S,SElemType &e){
if(S == NULL) return ERROR;
e = S -> date;
p = S;
S = S -> next;
delete p;
return OK;
}
取栈顶元素
SElemType GetTop(LinkStack S){
if(S!= NULL)
return S -> date;
}
栈与递归
一个对象包含自己或自己给自己定义
一个过程直接或间接调用自己
分治法求递归问题算法的一般形式
void p(参数表){
if(递归结束条件) 可以直接求解步骤; ------基本项
else p(较小的参数); ------归纳项
}
队列(queue)
队列是一种先进先出的线性表(FIFO)
一端插入一端删除
抽象类型定义
ADT Queue{
数据对象:
D = {ai|ai∈ElemSet,i=1,2,3,...n,n≥0}
数据关系:
R1 = {<ai-1,ai>|ai-1,ai∈D,i=2...,n}
约定a1端为队列头,an端为队列尾
基本操作:
初始化,入队,出队等
}ADT Queue
基础操作
InitQueue (&Q) 构造空队列
DestroyQueue (&Q) 销毁队列
ClearQueue (&Q) 清空队列
QueueEmpty(Q) 判空. 空=TRUE,
QueueLength(Q) 取队列长度
GetHead (Q,&e) 取队头元素,
EnQueue (&Q,e) 入队列
DeQueue (&Q,&e) 出队列
QueueTraverse(Q,visit()) 遍历
顺序队列
一维数组base[MAXQSIZE]表示
#define MAXQSIZE 100 //最大队列长度
Typedef struct{
QElemType *base; //初始化的动态分配存储空间
int front; //头指针
int rear; //尾指针
}SqQueue
初始状态 front = rear = 0
当 rear = MAXQSIZE
时发生溢出
若front = 0 rear = MAXQSIZE时
再入队 则为真溢出
若front != 0 rear = MAXQSIZE时
再入队 则为假溢出
对于假上溢如何解决 >>>
1.将对内元素依次向队头方向移动 (浪费时间)
2.循环:
思路:base[0] 接在 base[MAXQSIZE-1] 之后 ,若 rear + 1 == MAXQSIZE, 则令 rear = 0;
具体实现:用%的运算
插入元素:Q.base[Q.rear] = x;
Q.rear = (Q.rear + 1) % MAXQSIZE;
删除元素:x = Q.base[Q.front]
Q.front = (Q.front + 1 ) % MAXQSIZE
对于判断循环队空队满 >>>
当循环队列中队空队满都为 front == rear 如何解决
1.设标记
2.记录个数
3.少用一个元素空间 则队满: (rear + 1) % MAXQSZIE == front
初始化
Status lnitQueue(SqQueue &Q){
Q.base = new QElemType[MAXQSIZE];
if(!Q.base) exit(OVERFLOW);
Q.front = Q.rear = 0;
return OK;
}
求队列长度
int QueueLength(SqQueue Q){
return ((Q.rear - Q.front + MAXQSZIE) % MAXQZIE);
}
入队
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) % MAXSIZE;
return OK;
}
出队
Status DeQueue(SqQueue &Q, QElemType &e){
if(Q.rear = Q.front) return ERROR;
e = Q.base[Q.front];
Q.front = (Q.front + 1) % MAXQSZIE;
return OK;
}
取队头元素
SElemType GetHead(SqQueue Q){
if(Q.rear = Q.front)
return Q.base[Q.front];
}
链队
当无法估计长度时,则宜采用链队列
类型定义
#define MAXQSIZE 100
typedef struct Qnode{
QElemType data;
stuct Qnode *next;
}QNode,*QueuePtr;
typedef struct{
QueuePtr front;
QueuePtr rear;
}LinkQueue;
初始化
Status lnitQueue(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){
while(Q.front){
p = Q.front -> next;
free(Q.front);
Q.front = p;
}//Q.rear = Q.front -> next; free(Q.front); Q.front = Q.rear;
return OK;
}
入队
Status EnQueue(LinkQueue &Q, QElemType e){
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){
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;
delepe p;
return OK;
}
求链队列的队头元素
Status GetHead(LinkQueue Q, QElemType &e){
if(Q.front == Q.rear) return ERROR;
e = Q.front -> next -> data;
return OK;
}