数据结构-栈与队列

栈和队列

栈(Stack)

栈的概念:

栈(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;
}

队列(Queue)

队列的概念:

队列是一种限定性线性表。先进先出

  • 它只允许插入在表的一端,这端叫队尾。
  • 删除要在表的另一端,这端叫队首。
  • 插入操作叫“入队”或“进队”,删除操作叫“出队”或“退队”。
  • 当队列中无元素时,叫“空队列”。

顺序队列的类型定义如下:

#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;
    }
}

你可能感兴趣的:(数据结构,数据结构)