栈(stack)是一种指允许在一端进行插入和删除的线性表,它是一种操作受限的线性表。
栈中的数据元素用一个预设的足够长度的一维数组来实现:ElemType elem[Max].
栈顶是随者插入和删除而变化的。用int top来作为栈顶的指针,指明当前栈顶的位置,
同时将elem 和top封装在一个结构中。
#define Max 100
typedef struct
{
ELemType elem[Max];
int top;
}SeqStack;
定义一个指向顺序栈的指针:
SeqStack *s;
通常将0下标断设为栈底,这样空栈时栈顶指针s->top=-1;栈顶指针+1,即s->top++;
顺序栈的基本操作如下:
(1)置空栈:
SeqStack *InitStack()
{
SeqStack *s;
s=(SeqStack *)malloc(sizeof(SeqStack));
s->top=-1;
return s;
}
(2)判空栈
int empty(SeqStack *s)
{
if(s->top==-1)
return 1;
else
return 0;
}
(3)入栈
int Push(SeqStack *s,ElemType x)
{
if(s->top==Max-1)
return 0;
else
{
s->top++;
s->elem[s->top]=x;
return 1;
}
}
(4)出栈
int Pop(SeqStack *s,ElemType *x)
{
if(empty(s))
return 0;
else
{
*x=s->elem[s->top];
s->top--;
return 1;
}
}
(5)取栈顶元素
ElemType GetTop(SeqStack *s)
{
if(empty(s))
return 0;
else
return (s->elem[s->top]);
}
链栈的特点:
链栈的C语言定义如下:
typedef struct Stacknode
{
DataType data;
struct Stacknode *next;
} slStacktype;
(1)入栈操作:
//将元素x压入链栈top中
int PushLstack(slStacktype *top,DataType x)
{
slStacktype *p;//申请一个结点
if((p=(slStacktype *)malloc(sizof(slStacktype))==NULL)
return 0;
p->data=x;
p->next=top->next;
top->next=p;
return 1;
}
(2)出栈操作
//从链栈top中删除栈顶元素
DataType PopLstack(slStacktype *top)
{
slStack *p;
DataType x;
if(top->next==NULL)//空栈
{
printf("此栈为空!");
return 0;
}
p=top->next;
top->next=p->next;
x=p->data;
free(p);
return x;
}
队列是一种限定性线性表。先进先出
顺序队列的类型定义如下:
#define Max 100
typedef struct
{
ElemType elem[Max];
int rear,front;//队尾、队头指针
}SeQueue;
定义一个指向队列的指针变量:
SeQueue *sq;
申请一个顺序队列的存储空间:
sq=(SeQueue *)malloc(sizeof(SeQueue));
队列的数据区为:
sq->elem[0]~elem[Max-1]
队头指针为:
sq->front
队中的元素个数为:
m=(sq->rear)-(q->front);
置空队时:
sq->front=sq->rear=-1;
随者入队出队的进行,可能会使整个队列向后移动,如图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dWFkJv9t-1633783679870)(C:\Users\Onlylove\AppData\Roaming\Typora\typora-user-images\image-20211007233919421.png)]
循环队列的特点:
可以解决假溢出的现象
是将头尾相接的循环结构
头尾指针的关系不变,即头指示器front总是指向队列中实际队头元素的前面一个位置,而尾指示器rear总指向队尾元素。
入队时的队尾指针加一操作修改为:
sq->rear=(sq->rear+1)%Max;
出队时的队头指针加一操作修改为:
sq->front=(sq->front+1)%Max;
循环队列的类型定义如下:
typedef struct
{
ElemType elem[Max];
int front ,rear;
}CSeQueue;
(1)置空队
CSeQueue *InitQueue()
{
q=(CSeQueue *)malloc(sizeof(CSeQueue));
q->front=q->reat=Max-1;
return q;
}
(2)入队
int InSeQueue(CSeQueue *q,ElemType x)
{
if((q->rear+1)%Max==q->front)
{
printf("队满了");
return 0;
}
else
{
q->rear=(q->rear+1)%Max;
q->elem[q->rear]=x;
return 1;
}
}
(3)出队
int OutSeQueue(CSeQueue *q,ElemType *x)
{
if(q->front==q->rear)
{
printf("队空");
return 0;
}
else
{
q->front=(q->front+1)%Max;
*x=q->elem[q->front];
return 1;
}
}
(4)判队空
int EmptySeQueue(CSeQueue *q)
{
if(q->front==q->rear)
return 0;
else
return 1;
}
数据类型描述如下:
typedef struct node
{
DataType data;
struct node *next;
}QNode;
typedef struct
{
QNnode *front;
QNnode *rear;
}LQueue;
定义一个指向链队列的指针:
LQueue *q;
链队列中各种操作的实现也和单链表类似,只是限定插入操作在表尾进行,删除操作在表头进行,需要注意的是,在链队列的删除操作中,对于仅有一个元素结点的特殊情况,删除后还需要修改尾指针。
(1)创建一个带头结点的空队
LQueue *InitQueue()
{
LQueue *q;
QNode *p;
q=(LQueue *)malloc(sizeof(LQueue));//申请头尾指针结点
p=(QNode *)malloc(sizeof(QNode));//申请链队列头结点
p->next=NULL;
q->front=q->rear=p;
return q;
}
(2)入队
void InLQueue(LQueue*q,DataType x)
{
QNode *p;
p=(QNode *)malloc(sizeof(QNode));
p->data=x;
p->next=NULL;
q->rear->next=p;
q->rear=p;
}
(3)判队空
int empty(LQueue *q)
{
if(q->front==q->rear)
return 0;
else return 1;
}
(4)出队
int output(LQueue *q,DataType *x)
{
QNode *p;
if(empty(q))
{
printf("队空");
return 0;
}
else
{
p=q->front->next;
q->front->next=p->next;
*x=p->data;
free(p);
if(q->front->next==NULL)
q->rear=q->front;
return 1;
}
}