一、栈
先进后出 FILO (First In Last Out)
只允许在一端进行插入或删除操作的线性表入栈:放入元素
出栈:拿出元素
1 线性栈
入栈:
S.data[++S.top] = 1 : 表示 S.top=S.top+1 ; S.data[S.top] = 1(√)
S.data[S.top++] = 1 : 表示 S.data[S.top] = 1 ; S.top=S.top+1出栈:
S.data[S.top- -] = 1 : 表示 x = S.data[S.top] ; S.top=S.top-1 (√)
S.data[- -S.top] = 1 : 表示 S.top=S.top-1 ; x = S.data[S.top];
1.1 代码实现
typedef int ElemType;
typedef struct {
ElemType data[MaxSize];
int top;//栈顶 满栈 MaxSize-1 = S.top
}SqStack;
//修改操作传引用
//1. 初始化栈
void InitStack(SqStack& S)
{
S.top = -1;//栈顶
}
//2. 判断是否为空
bool StackEmpty(SqStack S)
{
if (-1 == S.top)
{
return true;
}
else {
return false;
}
}
//3. 入栈
bool Push(SqStack& S, ElemType x)
{
//判断是否满栈
if (S.top == MaxSize - 1)
{
return false;
}
S.data[++S.top] = x;//先top加加,再赋值
return true;
}
//4. 获取栈顶元素
bool GetTop(SqStack S, ElemType& m)
{
if (StackEmpty(S))
{
return false;
}
m = S.data[S.top];//保存到m
return true;
}
//5. 出栈
bool Pop(SqStack& S, ElemType& m)
{
if (StackEmpty(S))
{
return false;
}
m = S.data[S.top--];//m=S.data[S.top];S.top=S.top-1;
return true;
}
2 链栈
链表实现栈,规定所有操作都是在单链表的表头进行的。
链栈不存在栈满上溢的情况。
2.1 代码实现
//栈的链式存储结构
//构造节点
typedef struct StackNode {
ElemType data;
struct StackNode* next;
}StackNode, * LinkStackPtr;
//构造链栈
typedef struct LinkStack {
LinkStackPtr top;
int count;
}LinkStack;
//这里规定链栈没有头节点,Lhead指向栈顶元素
//1.插入元素 e为新的栈顶元素
bool Push(LinkStack* S, ElemType e) {
LinkStackPtr p = (LinkStackPtr)malloc(sizeof(StackNode));
p->data = e;
p->next = S->top; //把当前的栈顶元素赋值给新节点的直接后继
S->top = p; //将新的结点S赋值给栈顶指针
S->count++;
return true;
}
//2. 若栈不空,则删除S的栈顶元素,用e返回其值
bool Pop(LinkStack* S, ElemType* e) {
LinkStackPtr p;
if (StackEmpty(*S)) {
return false;
}
*e = S->top->data;
p = S->top; //将栈顶结点赋值给p
S->top = S->top->next; //使得栈顶指针下移一位,指向后一结点
free(p); //释放结点p
S->count--;
return true;
}
二、队列
先进先出(FIFO)
队列满: (Q.rear+1)%MaxSize == Q.front
1 顺序队列
初始状态(队空条件):Q.front == Q.rear == 0。
进队操作:队不满时,先送值到队尾元素,再将队尾指针加1。
出队操作:队不空时,先取队头元素值,再将队头指针加1。
2 循环队列
初始:Q.front = Q.rear=0。
队首指针进1:Q.front = (Q.front + 1) % MaxSize。
队尾指针进1:Q.rear = (Q.rear + 1) % MaxSize。
队列长度:(Q.rear - Q.front + MAXSIZE) % MaxSize。
2.1 代码实现
#define MaxSize 50
typedef int ElemType;
//循环队列
typedef struct {
ElemType data[MaxSize]; //只能存MaxSize-1个元素
int front, rear;// 队头队尾
}SqQueue;
// 1.队列初始化
void InitQueue(SqQueue& Q)
{
Q.front = Q.rear = 0;
}
//2. 判断队列是否为空
bool isEmpty(SqQueue Q)
{
return Q.rear == Q.front;
}
//3. 入队
bool EnQueue(SqQueue& Q, ElemType x)
{
if ((Q.rear + 1) % MaxSize == Q.front)//队列为满
{
return false;
}
Q.data[Q.rear] = x;//入队
Q.rear = (Q.rear + 1) % MaxSize;//队尾位置(指向可以放元素的位置
return true;
}
//4. 出队
bool DeQueue(SqQueue& Q, ElemType& x)
{
if (Q.rear == Q.front)//是否为空
{
return false;
}
x = Q.data[Q.front];//出队
Q.front = (Q.front + 1) % MaxSize;
return true;
}
3 链式队列
3.1 代码实现
typedef int ElemType;
typedef struct LinkNode {
ElemType data;
struct LinkNode* next;
}LinkNode;
typedef struct {
LinkNode* front, * rear;//头尾指针
}LinkQueue;//
//初始化
void InitQueue(LinkQueue& Q)
{
Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));
Q.front->next = NULL;
}
//入队 有头结点的链表
void EnQueue(LinkQueue& Q, ElemType x)
{
LinkNode* pnew = (LinkNode*)malloc(sizeof(LinkNode));
pnew->data = x;
pnew->next = NULL;//next为null
Q.rear->next = pnew;//尾指针指向pnew
Q.rear = pnew;//rear指向新的尾部
}
//出队
bool DeQueue(LinkQueue& Q, ElemType& x)
{
if (Q.rear == Q.front)//队列为空
{
return false;
}
//出队即相当于删除一个节点,从头部删除
LinkNode* q = Q.front->next;//拿到第一个节点
x = q->data;
Q.front->next = q->next;//让第一个节点断链
if (Q.rear == q)//如果删除了一个节点以后只有一个节点
{
Q.rear = Q.front;//指向最后一个节点
}
free(q);
return true;
}