栈和队列
是限定插入和删除操作只能在表的端点进行的线性表
栈
是只能在栈顶进行插入删除操作,先入后出
//顺序栈,栈顶指针指向栈顶元素的下一个位置
#define STACK_INIT_SIZE 100;//存储空间初始分配量
#define STACKINCREMENT 10;//存储空间分配增量
typedef struct{
SElemType *base;//栈底指针
SElemType *top;//栈顶指针
int stacksize; //当前已分配的存储空间
}SqStack;
Status GetTop(SqStack S,SElemType &e){
if(S.top == S.base) return ERROR;//栈为空
e = *(S.top-1);
return OK;
}
Status Push(SqStack &S,SElemType e){
if(S.top - S.base >= S.stacksize){
S.base=(ElemType *)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(ElemType));
S.top=S.base+S.stacksize;
S.stacksize+=STACKINCREMENT;
}
*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;
return OK;
}
这里主要写的都是循序栈,链栈差别不会太大,主要要注意头指针一直指向栈顶元素
void Push(LinkStack &Sl,SElemType e){
SNode *p=new SNode();
p->data=e;
p->next=top;
top=p;
}
栈的应用
-
括号匹配
-
表达式求值
表达式的三种标识方法:前缀、中缀、后缀
Exp = a x b + (c - d / e) x f
中缀转后缀
队列
先入先出,只能从队头出队,队尾入队
链队列
typedef struct QNode {// 结点类型
QElemType data;
struct QNode *next;
} QNode, *QueuePtr;
typedef struct { // 链队列类型
QueuePtr front; // 队头指针
QueuePtr rear; // 队尾指针
} LinkQueue;
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.rear==Q.front) return ERROR;
p=Q.front->next;
e=p->data;
Q.front->next=p->next;
if(Q.rear==p) Q.rear=Q.front;
return OK;
}
循环队列
是顺序映像,防止假溢出
判断队列满和队列空:
在循环队列中,队列满和队列空的判断条件都是Q.rear=Q.front
,所以无法辨别,为此我们选择牺牲一个存储空间,来分辨队列满和队列空
队列满:(rear + 1) % MaxSize == front
队列空:front == rear
队列中元素个数:(rear - front + MaxSize) % MaxSize
入队位置:rear = (rear+1) % MaxSize
出队位置:front = (front +1) % MaxSize
#define MAXQSIZE 100 //最大队列长度
typedef struct {
QElemType *base; // 动态分配存储空间
int front; // 头指针,若队列不空,
// 指向队列头元素
int rear; // 尾指针,若队列不空,指向
// 队列尾元素 的下一个位置
int queuesize;
} SqQueue;
Status EnQueue (SqQueue &Q, ElemType e) { // 插入元素e为Q的新的队尾元素
if ((Q.rear+1) % Q.queuesize == Q.front)
return ERROR; //队列满
Q.base[Q.rear] = e;
Q.rear = (Q.rear+1) % Q.queuesize;
return OK;
}
Status DeQueue(SqQueue &Q,ElemType e){
if(Q.front==Q.rear) return ERROR;//队列空
e = Q.base[Q.front];
Q.front = (Q.front+1) % MaxSize;
return OK;
}
特殊队列
双端队列:在队首和队尾都可以进行插入和删除
输入受限的双端队列:只能在队尾插入数据,在队尾和队首都可以删除
输出受限的双端队列:只能在队首输出,在队首和队尾都可以输入