栈是一种值允许在一端进行插入和删除的线性表,它是一种操作受限的线性表。
*允许进行插入和删除的一端称栈顶
*不允许进行插入和删除的一端称栈底
*不含元素的栈正空栈
*往栈中存入元素称入栈
*从栈中输出元素称出栈
特点:后进先出(LIFO)或先进后出(FILO)
栈的顺序存储结构:
顺序栈的类型描述:
#define MAXSIZE <栈最大元素数>
typedef struct
{
datatype data [MAXSIZE];
int top;
}SeqStack;
定义一个指向顺序栈的指针:SeqStack *s;
(1)置栈空:首先建立空间,然后初始化栈顶指针
SeqStack *Init_SeqStack()
{
SeqStack *s;
s = malloc(sizeof(SeqStack));
s -> top = -1;
return s;
}
(2)判栈空
int Empty_SeqStack(SeqStack *s)
{
if (s->top == -1)
return 1;
else
return 0;
}
(3)入栈
int Push_SeqStack(SeqStack *s, datatype x)
{
if (s->top == MAXSIZE - 1)
return 0; /*栈满不能入栈*/
else
{
s->top++;
s->data[s->top] = x;
return 1;
}
}
(4)出栈
int Pop_SeqStack(SeqStack *s, datatype *x)
{
if (Empty_SeqStack(s))
return 0; /*栈空不能出栈*/
else
{
*x = s->data[s->top];
s->top--;
return 1;
}/*栈顶元素存入*x, 返回*/
}
(5)取栈顶元素
datatype Top_SeqStack(SeqStack *s)
{
if (Empty_SeqStack(s))
return 0; /*栈空*/
else
return (s->data[s->top]);
}
对栈的操作应注意以下几点:
(1)对于顺序栈,入栈时,首先判栈是否满了,栈满的条件为:s->top == MAXSIZE-1,栈满时,不能入栈,否则出现空间溢出,引起错误,这种现象称为上溢。
(2)出栈和读栈顶元素操作,先判栈是否为空,为空时不能操作,否则产生错误。通常栈空时常作为一种控制转移的条件。
(3)取栈顶元素与出栈的不同之处在于出栈操作改变栈顶指针top的位置(栈顶指针下移一个位置),而取栈顶元素操作只是读出栈顶元素的值栈顶指针top位置不改变。
队列是另一种限定性表,它只允许插入在表的一端进行而删除在表的另一端进行,把允许插入的一端叫队尾,允许删除的一端叫对头。队列的插入操作通常称为入队列,删除操作则称为出队列。特点:“先进先出”(FIFO)
链队列的数据类型描述如下:
typedef struct node
{
datatype data;
struct node *next;
}QNode; /*链队结点类型*/
typedef struct
{
QNode *front;
QNode *rear;
}LQueue; /*将头尾指针封装在一起的链队*/
定义一个指向链队的指针: LQueue *q;
(1)创建一个带头结点的空队
LQueue *Init_LQueue()
{
LQueue *q, *p;
q = malloc(sizeof(LQueue)); /*申请头尾指针结点*/
p = malloc(sizeof(QNode)); /*申请链队尾结点*/
p-> next = NULL;
q->front = q->rear = p;
return q;
}
(2)入队
void InLQueue(LQueue *q, datatype x)
{
QNode *p;
p = malloc(sizeof(QNode)); /*申请新结点*/
p->data = x;
p->next = NULL;
q->rear->next = p;
q->rear = p;
}
(3)判队空
int Empty_LQueue(LQueue *q)
{
if (q->front == q->rear)
return 0;
else
return 1;
}
(4)出
队
int Out_LQueue(LQueue *q, datatype *x)
{
QNode *p;
if (Empty_LQueue(q))
{
printf("队空");
return 0;
}
else
{
p = q->front->next;
q->front->next = p->next;
*x = p->data; /*对头元素放入x中*/
free(p);
if (q->front->next == NULL)
q->rear = q->front; /*只有一个元素时,出队后队空,修改队尾指针*/
return 1;
}
}
注意:循环链队的创建中“q->front = q->rear = p;”即q->front和q->rear直接指向链表p的头结点,而q->front的next即链表p的头结点的next。队头指针(front)始终指向头结点,队尾指针(rear)指向当前最后一个元素结点。入队从队尾入,出队从队头出。