栈和队列是限定插入和删除总股本变更在表的端点进行的线性表表
栈--后进先出
必须利用栈的算法:数制匹配、表达式求值、括号匹配检测、八皇后问题、行编辑程序、函数调用、迷宫求解、递归调用的实现
插入和删除仅能在表尾进行。
顺序栈
设置top指针为指向栈顶元素、base指针指向栈底;但是为了操作方便,top一般指向栈顶元素之上的下标地址,stacksize表示栈的最大容量
空栈:base==top
栈满:top-base=stacksize
上溢:栈满,还要压入元素 下溢:栈空,还要弹出元素
一般视上溢为一种错误,下溢为一种结束条件
实现:
定义
#define MAXSIZE 100
typedef struct{
SElemType *base;//栈顶指针
SElemType *top;//栈底指针
int stacksize;//最大容量
}SqStack;
检查栈满?
Status StackEmpty(SqStack S){
if(S.top == S.base)
return TURE;
else
return FASLSE;
}
初始化
Status InitStack(SqStack &S)
{
S.base= new SElemtype[MAXSIZE];
if(!S.base) exit(OVERFLOW);//存储分配失败
S.top=S.base;//栈置空
S.stacksize = MAXSIZE;
return OK;
}
求长
int StackLength(SqStack S)
{
return S.top-S.base;
}
清空栈
Status ClearStack(SqStack S){
if(S.base) S.top = S.base;
return OK;
}
销毁栈
Staus DestroyStack(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.base == S.stacksize)//栈满
return ERROR;
*S.top++=e; //或者 *S.top=e; s.top++;
return OK;
}
出栈
Status Pop(SqStack &S,SElemType &e){
if(S.top == S.base)//空栈检测
return ERROR
e = *--S.top; //--S.top; e=*S.top;
return OK;
}
链栈
定义
typedef struck StackNode{
SElemType data;
struct StackNode *next;
}StackNode,*LinkStack;
LinkStack S;
头插法方便栈操作
链表的头指针就是栈顶;不需要头结点;基本不存在栈满的情况;空栈相当于头指针指向空;插入和删除仅在栈顶处执行
初始化
void InitStack(LinkStack &S){
S=NULL;
return OK;
}
判空
Status StackEmpty(LinkStack S)
{
if(S==NULL) return TRUE;
else return FALSE;
}
入栈
Status Push(LinkStack &S,SElemType e){
p = new StackNode;//生成结点p
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(LinkStack S){
if(S!=NULL)
return S->data;
}
栈与递归
定义:
若一个对象部分包含自己,或者用自己给自己定义,称这个对象是递归的(链表)
若一个过程直接或间接地调用自己,称这个过程是递归过程(n的阶乘)
经典递归问题:递归定义的数学函数、具有递归特性的数据结构、可递归求解的问题
分治法求解的一般形式
void p(参数表){
if(递归结束条件) 可直接求解步骤;--基本项
else p(较小的参数); --归纳项
}
Ex:
long Fact(long n){
if(n==0) return 1;//基本项
else return n*Fact(n-1);//归纳项
}
队列--先进先出
顺序队列
定义
#define MAXQSIZE 100
typedef Sturct{
SElemType *base;//初始化的动态分配存储空间
int front;//头指针
int rear;//尾指针
}SqQueue;
解决假上溢(还有内存空间但是Q.rear指向队尾)
1.将队中元素依次前移 缺点:浪费时间(所有元素均需移动)
2.rear=maxqsize的时候让其指向头部空间,front为maxqsize时同理
计算方法:求模运算 插入Q.base[Q.rear] = x;
Q.rear=(Q.rear+1)%MAXQSIZE;
删除x=Q.base[s.front];
Q.front=(Q.front+1)%MAXQSIZE
循环队列判断队空和队满(front==rear)
1.额外设置一个表示来判断 2.少使用一个变量 3.另设一个元素记录个数
2的计算方式 (rear+1)%MAXQSIZE == front
队列的初始化
Status InitQueue(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+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; //队尾指针+1
retturn 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;//对头指针+1
return OK;
}
链式队列
定义
#define MAXQSIZE 100
typedef struct Qnode{
QElemType data;
struct Qnode *next;
}QNode,*QueuePtr;
初始化
Status InitQueue(LinkQueue &Q){
Q.front==Q.rear = new QNode();
if(!Q.front) exit(OVERFLOW);
Q.front->next=NULL;
return OK;
}
销毁
Status DestroyQueue(LinkQueue &Q){
while(Q.front){
p=Q.front->next; delete Q.front; Q.front=p;
//Q.rear = Q.front->next; delete Q.front; Q.front=Q.rear;
}
return OK;
}
入队
Status EnQueue(LinkQueue &Q,QElemType e){
p= new 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;
delete p;
return OK;
}