数据结构算法——栈和队列(C语言版)

本文介绍了栈和队列这两种基础的数据结构,包括它们的基本概念、特点以及代码操作。栈是限定在一头进行插入和删除的线性表,遵循后进先出(LIFO)的原则;队列则是允许在一头插入,在另一头删除的线性表,遵循先进先出(FIFO)的原则。文章还详细讲解了栈的顺序存储结构、队列的链式存储结构以及循环队列的概念,并给出了相应的入栈、出栈、入队和出队的代码实现。
摘要由CSDN通过智能技术生成

栈和队列在数据结构和算法中算是比较基础的知识,两者之间有着相似之处,也有各自的特点。今天我们来看一下栈和队列的基本概念代码操作

目录

一.栈

 1.栈的基本概念

 2.栈的相关代码操作

(1).栈的顺序存储结构

(2).创建一个栈

(3).入栈操作

(4).出栈操作

二.队列

1.队列的基本概念

2.队列的相关代码操作

(1).队列的链式存储结构

(3).入队列操作

(4).出队列操作

 3.循环队列的基本概念

(1).定义一个循环队列的操作

(2).初始化一个循环队列

(3).入队列操作

(4).出队列操作


一.栈

 1.栈的基本概念

(Stack)是一种特殊的线性表,是限定只在一端进行插入与删除的线性表。

在栈中,一端是封闭的,既不能插入元素,也不能删除元素;而另一端是开口的,既能插入元素,也能删除元素。通常称插入、删除的这一端为“栈顶”(top),另一端为“栈底”(bottom)。

 

 栈的特点:(1).栈只能从栈顶进行插入和删除。

                   (2).栈的修改原则:先进后出后进先出

                   (3).栈底指针不变,栈中元素随着栈顶指针变化而变化


 

 2.栈的相关代码操作

(1).栈的顺序存储结构

typedef struct
{
    Elemtype *base;        //指向栈底的指针
    Elemtype *top;         //指向栈顶的指针
    int stackSize;         //表示栈当前可使用的最大容量
}sqStack;

(2).创建一个栈

#define STACK_INIT_SIZE 100       //宏定义栈的最大容量
initStack(sqStack *s)
{
    s->base = (Elemtype *)malloc(STACK_INIT_SIZE * sizeof(Elemtype) );    //申请空间
    if( !s->base )    //若申请失败则退出
        exit(0);
    s->top = s->base;    //最开始(空栈)栈顶就是栈底
    s->stackSize = STACK_INIT_SIZE;

(3).入栈操作

入栈操作要在栈顶进行,每次向栈中压入一个数据,top指针就要+1.直到栈满为止;特别要注意栈是否已满。

#define SATCKINCREMENT 10    //宏定义增长量为10

Push(sqStack *s,ElemType e)
{
    if( s->top - s->base >= s->stackSize )    //如果栈满,则追加空间
    {
        s->base = (ElemType *)realloc(s->base,(s->stackSize + SATCKINCREMENT) * sizeof(ElemType));    //调用realloc函数追加空间
        if( !s->base )
            exit(0);
        s->top = s->base + s->stackSize;    //设置栈顶(栈底+当前容量)
        s->stackSize = s->stackSize + SATCKINCREMENT;    //设置栈的最大容量(原基础上+10)
    }
    
    *(s->top) = e;
    s->top++;
}

(4).出栈操作

出栈操作就是在栈顶取出数据,栈顶指针随之下移的操作,每当从栈内取出一个元素后,栈的当前容量就-1

Pop(sqStack *s,ElemType *e)
{
    if( s-top ==s->base)    //若栈已空,则返回
        return;
    *e = *--(s->top);    将栈的最上面的元素取出放到变量e中,并且top-1
}

 

二.队列

1.队列的基本概念

队列(queue)是指允许在一端进行插入操作,而在另一端进行删除操作的线性表。允许删除的一端称为队首(front),允许插入的一端称为队尾(rear)。

 

队列的特点:(1).队列只允许在队尾进行插入,队首进行删除

                      (2).队列的修改原则:先进先出后进后出

                       (3).队列中的元素随着队尾指针和队首指针的变化而变化


 

2.队列的相关代码操作

(1).队列的链式存储结构

typedef struct QNode {
    ElemType data;    //数据
    struct QNode *next;    //指向下一个元素的指针
} QNode, *QueuePrt;

typedef struct {
    QueuePrt front, rear;    //队头、尾指针
} LinkQueue;

(2).创建一个队列

创建一个队列要完成两个任务:一是在内存中创建一个头结点,二是将队列的头指针和尾指针都指向这个生成的头结点,因为此时是空队列。

initQueue(LinkQueue *q)
{
    q->front=q->rear=(QueuePtr)malloc(sizeof(QNode));    //创建一个头结点并且使队列的头指针和尾指针指向该头结点
    if(!q->front)
        exit(0);
    q->front->next = NULL;    //此时为空队列
}

(3).入队列操作

主要是将最后一个元素指向下一个元素的指针由NULL变成新入元素的指针,并且将尾指针(rear)从指向最后一个元素变成指向新入队列的元素

InsertQueue(LinkQueue *q,ElemType e)    //队列q,新入队列元素e
{
    QueuePtr p;
    p = (QueuePtr)malloc(sizeof(QNode));    //生成新结点p,暂时存放元素e的值
    if( p == NULL )
        exit(0);
    p->data = e;
    p->next = NULL;    //新元素的next要指向NULL
    q->rear->next = p;    //将队列的尾指针指向新元素的指针
    q->rear = p;    //将新入元素的指针赋给尾指针
}

(4).出队列操作

出队列操作是将队列中的第一个元素移出,队列头指针不发生改变改变头结点的next指针即可。

DeleteQueue(LinkQueue *q,ElemType *e)
{
    QueuePtr p;    //生成一个结点p用来存放要出队列的元素并最后释放掉
    if( q->front == q->rear )    //队列为空
        return;
    p = q-front->next;
    *e = p->data;
    q->front->next = p->next;
    if( q->rear == p )    //队列只有一个元素
        q->rear = q->front;
    free(p);    //释放结点p
}

 

 3.循环队列的基本概念

循环队列就是将队列存储空间的最后一个位置绕到第一个位置,形成逻辑上的环状空间,供队列循环使用。从队列首指针front指向的后一个位置到队列尾指针rear指向的位置之间所有的元素均为队列中的元素。循环队列的实现只需要灵活改变front和rear指针即可,也就是然后让front或rear指针不断加1,即使超出了地址范围,也会自动从头开始。我们可以采取取模运算来实现:

-(rear+1)%QueueSize

-(front+1)%QueueSize

取模就是取余数的意思,取模运算得到的值永远不会大于除数,随着被除数的增大,取模运算的值会一直循环下去。

(1).定义一个循环队列的操作

#define MAXSIZE 100
typedef struct
{
    ElemType *base;    //用于存放内存分配基地址
    int front;
    int rear;
}

(2).初始化一个循环队列

initQueue(cycleQueue *q)
{
    q->base = (ElemType *)malloc(MAXSIZE *sizeof(ElemType));    //生成一个空间给基地址
    if( !q->base )
        exit(0);
    q->front = q->rear = 0;    //一开始为空队列
}

(3).入队列操作

InsertQueue(cycleQueue *q,ElemType e)
{
    if((q->rear+1)%MAXSIZE == q->front)    //队列已满
        return;
    q->base[q->rear] = e;    //模拟数组,将e存入队列
    q->rear = (q->rear+1)%MAXSIZE;    //尾指针“加”1
}

(4).出队列操作

DeleteQueue(cycleQueue *q,ElemType *e)
{
    if(q->front == q->rear)    //队列为空
        return;
    *e=q->base[q->front];    //将要出队列的元素给e
    q->front=(q->front+1)%MAXSIZE;    //将头指针指向下一个
}

结尾:人之所以痛苦,在于追求错误的东西。如果你不给自己烦恼,别人也永远不可能给你烦恼。

希望我们能放弃追求某些东西,这样我们才会活得快乐。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值