栈---后进先出
如果问题求解的过程具有”后进先出"的天然特性的话,则求解的算法中也必然需要利用"栈”
栈和队列是限定插入和删除只能在表的"端点”进行的线性表。
栈(stack) 是一个特殊的线性表,是限定仅在一端(通常是表尾)进行插入和删除操作的线性表。
表尾(即an端)称为栈顶(Top;表头(即a1端)称为栈底Base.
插入元素到栈顶(即表尾)的操作,称为入栈。== PUSH(x)
从栈顶(即表尾)删除最后个元素的操作, 称为出栈。==POP(y)
LnitStack(&S)初始化操作
操作结果:构造一个空栈S。
DestroyStack(&S)销毁栈操作
初始条件:栈S已存在。
操作结果:栈S被销毁。
StackEmpty(S)判定S是否为空栈
操作结果:若栈S为空栈,则返回TRUE,否则FALSE。
StackLength(S)求栈的长度
操作结果:返回S的元素个数,即栈的长度。
GetTop(S, &e)取栈顶元素
初始条件:栈S已存在且非空。
操作结果:用e返回S的栈顶元素。
ClearStack(&S)栈置空操作
操作结果:将S清为空栈。
Push(&S,e)入栈操作
操作结果:插入元素e为新的栈顶元素。
Pop&S, &e)出栈操作
操作结果:删除S的栈顶元素an,并用e返回其值。
顺序栈的表示和实现
存储方式:同一般线性表的顺序存储结构完全相同,利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素。栈底-般在低地址端。
附设top指针,指示栈顶元素在顺序栈中的位置。
另设base指针,指示栈底元素在顺序栈中的位置。
另外,用stacksize表示栈可使用的最大容量
空栈:base == top是栈空标志
栈满:top-base==stacksize
顺序栈的表示
#define MAXSIZE 100
typedef struct{
SElemType *base;//栈底指针
SElemType *top;//栈顶指针
int stacksize;/栈可用最大容量
}SqStack;
顺序栈的初始化
Status lnitStack(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;
}
顺序栈判断栈是否为空
Status StackEmpty(SqStack S){//若栈为空,返回TRUE;否则返回FALSE
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;
销毁顺序栈
Status DestroyStack(SqStack &S){
if(S.base){
delete S.base;
S.stacksize = 0;
S.base = S.top = NULL;
顺序栈的入栈
(1)判断是否栈满,若满则出错(上溢)
(2)元素e压入栈顶
(3)栈顶指针加1
Status Push(SqStack &S,sElemType e){
if(S.top - S.base == S.stacksize)//栈满
return ERROR;
*S.top++ = e;// == *S.top = e;S.top++;
顺序栈的出栈
(1)判断是否栈空,(若空则出错(下溢)
(2)获取栈顶元素e
(3)栈顶指针减1
Status Pop(SqStack &S,SElemType &e){//若栈不空,则删除S的栈顶元素,用e返回其值/并返回OK;否则返回ERROR
if(S.top == S.base)//等价于 if(StackEmpty(S))
return ERROR;
e = *--S.top;
return OK;
链栈是运算受限的单链表,只能在链表头部进行操作
typedef struct StackNode{
SElemType data;
struct StackNode *next;
}StackNode, *LinkStack;
LinkStack S;
链表的头指针就是栈顶
不需要头结点
基本不存在栈满的情况
空栈相当于头指针指向空
插入和删除仅在栈顶处执行
链栈的初始化
void lnitStack(LinkStack &S){//构造一个空栈,栈顶指针置为空
S=NULL;
判断链栈是否为空
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; //将新结点数据域置为e
p->next = S; //将新结点插入栈顶
S = p; //修改栈顶指针
链栈的出栈
Status Pop(LinkStack &S,ElemType &e){
if(S == NULL) return ERROR;
e = S->data;
p = S;
S = S->next;
delete p;
取栈顶元素
SElemType GetTop(LinkStack S){
if(S!=NULL)
return S->data;
若一个对象部分地包含它自己,或用它自己给自己定义,则称这个对象是递归的;
若一个过程直接地或间接地调用自己,则称这个过程是递归的过程。
分治法求解递归问题算法的一般形式:
void p(参数表){
if(递归结束条件) 可直接求解步骤;--基本项
else p(较小的参数);---归纳项
队列(queue)是一种先进先出的线性表。在表一端插入(表尾) ,在另一端(表头)删除
队列的顺序表示一 用一-维数组base[MAXQSIZE]
#define MAXQSIZE 100//最大队列长度
Typedef struct{
QElemType *base;//初始化分配存储空间
int front;//头指针
int rear;//尾指针
}SqQueue;
循环队列的操作一队列的初始化
Status lnitQueue(SqQueue &Q){
Q.base = new QElemType[MAXQSIZE]//分配数组空间
//Q.base = (QElemType*)
//malloc(MAXQSIZE*sizeof(QElemType));
if(!Q.base) exit(OVERFLOW);
Q.front = Q.rear =0; //存储分配失败
return OK; //头指针尾指针置为0,队列为空
循环队列的操作一求队列的长度
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
}
循环队列的操作一循环队列出队
Status EnQueue(SqQueue &Q,QElemType e){
if(Q.front == Q.rear) return ERROR;//队空
e=Q.base[Q.front]; //保存队头元素
Q.front = (Q.front+1)%MAXQSIZE://队头指针+1
循环队列的操作一 取队头元素
SElemType GetHead(SqQuere Q){
if(Q.front!=Q.rear) //队列不为空
return Q.base[Q.front];//返回队头指针元素的值,队头指针不变
若用户无法估计所用队列的长度,则宜采用链队列
#define MAXQSIZE 100//最大队列长度
typedef struct Qnode{
QElemType data;
stuct Qnode *next;
}QNode,*QuenePtr;
链队列的操作一链队列初始化:
Status lnitQueue(LinkQueue &Q){
Q.front = Q.rear = (QueuePtr) malloc(sizeof(QNode));
if(!Q.front) exit(OVERFLOW);
Q.front->next=NULL;
链队列的操作一销毁链队列
算法思想:从队头结点开始,依次释放所有结点
Status DestroyQueue(LinkQueue&Q){
while(Q.front){
p=Q.front->next; free(Q.front); Q.front = p;
链队列的操作一将元素e入队
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;
delete p;