作为线性表的一种,栈和队列都具有两种存储方式,顺序存储和链式存储,链式存储的好处是开始不用担心长度。
栈(stack)
后进先出的线性表。它的特点是只能在表尾(栈顶)进行插入和删除操作。
顺序栈:
typedef int SElemType; /*数据元素类型假设为int*/
typedef struct
{
SElemType data[MAXSIZE];
int count; /*用于栈顶指示,从0开始计*/
}SqStack;
/*进栈操作push,出栈操作pop*/
void Push(SqStack *S, SElemType e)
{
if (S->count == MAXSIZE - 1) /*栈满*/
return;
S->count++;
S->data[S->count] = e; /*top先加1,将插入元素给栈顶空间*/
}
void Pop(SqStack *S, SElemType *e)
{
if (S->count == -1) /*栈空*/
return;
*e = S->data[S->count]; /*先把栈顶元素取出,top再减1*/
S->count--;
}
链栈:
将栈顶指针和链表的头指针结合;链表就不需要判断“栈满”,只需要申请内存。
/*链栈*/
typedef struct StackNode
{
SElemType data;
struct StackNode *next;
}StackNode, *LinkStackPtr;
typedef struct LinkStack
{
LinkStackPtr top; /*栈顶放头结点*/
int count;
}LinkStack;
/*链栈的入栈*/
void Push(LinkStack *S, SElemType e)
{
LinkStackPtr p = (LinkStackPtr)malloc(sizeof(StackNode));
p->data = e;
p->next = S->top; /*原来的栈顶给新元素的后继*/
S->top = p;
S->count++;
}
/*链栈的出栈*/
void Pop(LinkStack *S, SElemType *e)
{
LinkStackPtr p;
if (StackEmpty(*S))
return;
*e = S->top->data;
p = S->top;
S->top = p->next;
S->count--;
free(p);
}
队列(queue)
先进先出的线性表。只允许在一端(队尾)进行插入,另一端(队头)进行删除。
循环队列:
为了解决“假溢出”的问题,一般队列都是循环队列。
为了区别“队满”和“队空”情况,rear 指向队尾元素的后一个位置,把 front=rear 认为是队空,而队满的条件是 (rear+1)%QueueSize=front。(队列还保留一个元素空间)
/*循环队列的顺序存储*/
typedef int QElemType;
typedef struct
{
QElemType data[MAXSIZE];
int front; /*指示头指针*/
int rear; /*指示尾指针.若队列不为空,指向队尾元素的下一个位置*/
}SqQueue;
/*初始化队列*/
void InitQueue(SqQueue *Q)
{
Q->front = 0;
Q->rear = 0;
}
/*求队列长度,当前队列元素个数*/
int QueueLength(SqQueue Q)
{
return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;
}
/*入队和出队*/
void EnQueue(SqQueue *Q, QElemType e)
{
if ((Q->rear + 1) % MAXSIZE == Q->front) /*判断队满*/
return;
Q->data[Q->rear] = e; /*从队尾插入*/
Q->rear = (Q->rear + 1) % MAXSIZE; /*rear指针向后移动,若到边界就转到数组头部*/
}
void DeQueue(SqQueue *Q, QElemType *e)
{
if (Q->rear == Q->front) /*判断队空*/
return;
*e = Q->data[Q->front]; /*队头出元素*/
Q->front = (Q->front + 1) % MAXSIZE; /*front指针向后移动*/
}
链队列:
空队列时,front和rear都指向头结点;非空时,front指向头结点,rear指向尾结点(不是队尾后一个位置);链表就不需要判断“队满”,只需要申请内存。
/*链式队列*/
typedef int QElemType;
typedef struct QNode /*结点结构*/
{
QElemType data;
struct QNode *next;
}QNode, *QueuePtr;
typedef struct /*队列的链表结构*/
{
QueuePtr front, rear;
}LinkQueue;
/*入队和出队*/
void EnQueue(LinkQueue *Q, QElemType e)
{
QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
p->data = e;
p->next = NULL;
Q->rear->next = p;
Q->rear = p;
}
void DeQueue(LinkQueue *Q, QElemType *e)
{
QueuePtr p;
if (Q->front == Q->rear) /*因为front是头结点,而不是第一个结点*/
return;
p = Q->front->next;
*e = p->data;
Q->front->next = p->next;
if (p = Q->rear) /*如果只有一个元素*/
Q->rear = Q->front; /*将队尾指向头指针,不能反了*/
free(p);
}