栈与队列
栈的定义
栈(stack)是限定仅在表尾进行插入或删除操作的线性表。因此,对栈来说,表尾端有其特殊含义,称为栈顶(top),相应的,表头端称为栈底(bottom)。不含元素的空表称为空栈。因为仅在表尾进行操作所以符合先进后出的规律。
栈的实现
栈的定义如下:
#define STACK_INIT_SIZE 100 //定义初始分配空间大小
typedef struct {
SElemType* base; //栈顶
SElemType* top; //栈底
int stacksize;
}SqStack;
栈的初始化
栈的初始化需要先定义栈的大小,这个可以提前定义。
Status InitStack(SqStack* S)//构造一个空栈
{
S->base = (SElemType*)malloc(STACK_INIT_SIZE * sizeof(SElemType));//分配储存空间
if (!S->base) //分配空间失败
exit(OVERFLOW);
S->top = S->base;
S->stacksize = STACK_INIT_SIZE;
return OK;
}
栈的删除
栈的删除,只需要将栈顶与栈底相连,即可删除栈中所有元素。
Status Delete(SqStack* S)//用e返回栈顶元素并删除栈顶元素
{
if (S->top == S->base)//栈为空
return ERROR;
S->top--;
return OK;
}
栈的压入
栈的压入,先将栈顶元素压入,然后移动栈顶指针,这样就将元素压入。
Status Push(SqStack* S, SElemType e)//插入元素e为新的栈顶元素
{
if (S->top - S->base >= S->stacksize)
{
S->base = (SElemType*)realloc(S->base, (S->stacksize + STACKINCREMENT) * sizeof(SElemType));//分配新储存空间
if (!S->base) exit(OVERFLOW); //分配空间失败
S->top = S->base + S->stacksize;
S->stacksize += STACKINCREMENT;
}
*S->top++ = e;
return OK;
}
栈顶元素的取出
一下函数中Pop函数与GetTop函数类似,但是还是有区别所以功能上也有不同。由于Pop函数中栈用的是指针,所以栈顶指针会移动,则会删除栈顶元素并返回栈顶元素。而GetTop函数没有用到指针,只会返回栈顶元素不会删除栈顶元素。
Status Pop(SqStack* S, SElemType* e)//用e返回栈顶元素并删除栈顶元素
{
if (S->top == S->base)//栈为空
return ERROR;
*e = *(--S->top);
return OK;
}
Status Delete(SqStack* S)//删除栈顶元素
{
if (S->top == S->base)//栈为空
return ERROR;
S->top--;
return OK;
}
Status GetTop(SqStack S, SElemType* e)//返回栈顶元素
{
if (S.top == S.base)//栈为空
return ERROR;
*e = *(--S.top);
return OK;
}
队列的定义
和栈相反,队列(queue)是一种先进先出的线性表它只允许在表的一端进行插入,而再另一端删除元素。在队列中,允许插入的一端叫做队尾(rear),允许删除的一端则称为队头(front)。
有时为了节省空间会有双端队列,还有循环队列等。
队列的实现
队列的定义如下:
typedef struct {
QueuePtr front; // 队头指针
QueuePtr rear; // 队尾指针
}LinkQueue;
队列的初始化
Status InitQueue(LinkQueue &Q) // 创建一个新队列
{
Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
if(!Q.front) exit(OVERFLOW); // 分配存储失败
Q.front->next = NULL;
return OK;
}
队列的删除
队列的删除与栈的删除类似,使对头和队尾相连即可
Status DestroyQueue(LinkQueue &Q) // 销毁队列
{
while(Q.front){
Q.rear = Q.front->next;
free(Q.front);
Q.front = Q.rear;
}
return OK;
}
队列的插入
Status EnQueue(LinkQueue &Q, QueuePtr s) // 插入元素 e 为 Q 的新的队列元素
{
s->next = NULL; // 队尾 next == NULL,有 data
Q.rear->next = s;
Q.rear = s; // 更新队尾
return OK;
}
队头元素的取出
Status DeQueue(LinkQueue &Q, QElemType &e) //用于返回路径
// 若对头不空,则删除对头元素,用 e 返回其值,并返回 OK,否则返回 ERROR
{
if(Q.front == Q.rear) return ERROR;
QueuePtr p = Q.front->next; // Q.front 没有 data, next != NULL(除非空队列)
e = p->data;
Q.front->next = p->next; // 更新队头
if(Q.rear == p) Q.rear = Q.front; // 队列为空了
free(p);
return OK;
}
以上便是栈与队列的基本操作,我的知识有限,如果大家有其他想法可以提出来。