一、顺序栈的表示和实现
// 顺序栈的存储结构
#define MAXSIZE 100
typedef int SElemType;
typedef struct {
SElemType *base; // 栈底指针
SElemType *top; // 栈顶指针
int stacksize; // 栈可用的最大容量
} SqStack;
其中base指针始终指向栈底位置,top指针指向栈顶的位置(栈顶元素的头上)初始值top和base都指向栈底。
顺序栈的初始化
typedef int Status;
Status InitStack(SqStack &S) {
S.base = (SElemType *)malloc(sizeof(SElemType) * MAXSIZE); // 将空间分配到base指针上
if(S.base) exit(0); // 存储分配失败
S.top = S.base; // 让头指针指向分配好空间的base
S.stacksize = MAXSIZE;
return 1;
}
入栈 / 压栈
Status Push(SqStack &S, SElemType e) {
// 插入元素e为新的栈顶元素
if(S.top - S.base == S.stacksize) return 0; // 栈满
*S.top++ = e; // 元素e入栈,栈顶指针加1
return 1;
}
出栈 / 弹栈
Status Pop(SqStack &S, SElemType &e) {
// 删除栈顶元素,用e返回其值
if(S.top == S.base) return 0; // 栈空
e = *--S.top; // 先让top降下来指着栈顶元素,然后赋值给e
return 0;
}
取栈顶元素
SElemType GetTop(SqStack S) {
// 返回栈顶元素,不修改栈顶指针
if(S.top != S.base) { // 栈非空
return *(S.top - 1);
}
}
二、链栈的表示和实现
// 链栈的存储结构
typedef struct StackNode {
ElemType data;
struct StackNode *next;
} StackNode, *LinkStack;
链栈的头部作为栈顶,一路指下去正好是出栈的顺序。为了方便插入和删除,没必要像单链表附加头结点。
链栈的入栈
Status Push(LinkStack &S, SElemType e) {
// 在栈顶插入元素e
LinkStack p = (LinkStack)malloc(sizeof(StackNode));
p->data = e;
p->next = S; // 新节点下一位指向头指针
S = p; // 头指针移动到新的头指针
return 1;
}
链栈的出栈
Status Pop(LinkStack &S, SElemType &e) {
// 删除栈顶元素,用e返回其值
if(S == NULL) return 0; // 栈空
e = S->data;
LinkStack p = S; // 保存栈顶元素,方便释放空间
S = S->next; // 栈顶指针向下移动
free(p);
return 1;
}
取栈顶元素
SElemType GetTop(LinkStack S) {
// 返回栈顶元素,不修改栈顶指针
if(S != NULL) { // 栈非空
return S->data;
}
}
三、循环队列---顺序表示和实现
#define MAXQSIZE 100
typedef int QElemType;
typedef struct {
QElemType *base; // 存储空间的基地址
int front; // 头指针
int rear; // 尾指针
} SqQueue;
队列空:Q.front == Q.rear 队列满:(Q.rear + 1) % MAXQSIZE == Q.front
初始化
Status InitQueue(SqQueue &Q) {
// 构造空队列Q
Q.base = (QElemType *)malloc(sizeof(QElemType) * MAXQSIZE);
if(!Q.base) return 0; // 储存空间分配失败
Q.front = Q.rear = 0; // 头指针和尾指针置为0,队列空
return 1;
}
求队列长度
int QueLength(SqQueue Q) {
// 返回队列元素个数,即队列的长度
return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
}
循环队列的入队
Status EnQueue(SqQueue &Q, QElemType e) {
// 插入元e为Q的新的队尾元素
if((Q.rear + 1) % MAXQSIZE == Q.front)
return 0; // 队尾指针加1正好到队头,说明堆满
Q.base[Q.rear] = e;
Q.rear = (Q.rear + 1) % MAXQSIZE;
return 1;
}
出队
Status DeQueue(SqQueue &Q, QElemType &e) {
// 删除Q的队头元素,用e返回其值
if(Q.front == Q.rear) return 0; // 队空
e = Q.base[Q.front];
Q.front = (Q.front + 1) % MAXQSIZE; // 队头指针加1
return 1;
}
取循环队列的队头元素
SElemType GetHead(SqQueue Q) {
// 返回Q的对头元素,不修改头指针
if(Q.front != Q.rear) { // 队列非空
return Q.base[Q.front];
}
}
四、链队---队列的链式表示和实现
// 队列的链式存储结构
typedef struct QNode {
QElemType data;
struct QNode *next;
} QNode, *QueuePtr;
typedef struct {
QueuePtr front; // 队头指针
QueuePtr rear; // 队尾指针
} LinkQueue;
链队的初始化
Status InitQueue(LinkQueue &Q) {
// 构造一个空队列Q
Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
Q.front->next = NULL; // 头结点置空
return 1;
}
构造的链队是有头结点的
入队
Status EnQueue(LinkQueue &Q, QElemType e) {
// 插入元素e为Q的新队尾元素
QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
p->data = e;
p->next = NULL;
Q.rear->next = p; // 插入新节点到队尾
Q.rear = p;
return 1;
}
出队
Status DeQueue(LinkQueue &Q, QElemType &e) {
// 删除Q的队头元素,用e返回其值
if(Q.front == Q.rear) return 0; // 队列空
QueuePtr p = Q.front->next; // p指向队头元素
e = p->data;
Q.front->next = p->next; // 头结点指向队头的下一个元素
if(Q.rear == p) Q.rear = Q.front; // 空队,则尾指针指向头结点
free(p);
return 1;
}
取队头元素
SElemType GetHead(LinkQueue Q) {
// 返回队头元素,不改变指针
if(Q.front != Q.rear) { // 队非空
return Q.front->next->data; // 返回队头元素
}
}