数据结构C(5)——栈和队列的定义和特点、栈的定义和特点、队列的定义和特点、栈的表示和操作的实现、链栈的表示和实现、栈与递归、队列的表示和操作的实现

本文详细介绍了栈和队列的基本概念、特点以及它们在数据结构中的应用。栈是一种后进先出的数据结构,常用于实现递归等操作;队列则遵循先进先出的原则,常见于任务调度。文章还分别阐述了顺序栈和链栈的表示与操作,以及顺序队列和链式队列的实现方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、栈和队列的定义和特点
  • 栈和队列是两种常用的、重要的数据结构
  • 栈和队列是限定插入和删除只能在表的“端点”进行的线性表
    • 栈和队列是线性表的子集(是插入和删除位置受限的线性表)

栈——先进后出、后进先出

队列——先进先出

二、栈的定义和特点
  • 栈(stack)是一个特殊的线性表,是限定仅在一端(通常是表尾)进行插入和删除操作的线性表
  • 又称为后进先出的线性表,简称LIFO结构
  • 表尾(即an端)称为栈顶Top;表头(即a1端)称为栈底Base
  • 插入元素到栈顶(即表尾)的操作,称为入栈
  • 栈顶(即表尾)删除最后一个元素的操作,称为出栈
  • “入”=PUSH(x) “出”=POP(y)
三、队列的定义和特点
  • 队列(queue)是一种先进先出(FIFO)的线性表。在表一端插入(表尾),在另一端(表头)删除
  • 逻辑结构:与同线性表相同,仍为一对一关系
  • 存储结构:顺序队或链队,以循环顺序队列更常见
四、栈的表示和操作的实现
  • 空栈:base==top 是栈空标志

  • 栈满:top-base==stacksize

  • 栈满时的处理方法

    • 报错,返回操作系统
    • 分配更大的空间,作为栈的存储空间,将原栈的内容移入新栈
  • 使用数组作为顺序栈存储方式的特点:

    • 简单,方便,单易产生溢出(数组大小固定)

      • 上溢(overflow):栈已经满,又要压入元素
      • 下溢(underflow):栈已经空,还要弹出元素

      注:上溢是一种错误,使问题的处理无法进行;而下溢一般认为是一种结束条件,即问题处理结束

1、栈的初始化
void InitStack(SeqStack *S)
{
    S->top=-1;
}
2、判断栈空
int IsEmpty(SeqStack S)
{
    if(S.top==-1)
        return TRUE;
    else
        return FALSE;
}
3、判断栈满
int IsFULL(SeqStack S)
{
    if(S.top==StackSize-1)
        return TRUE;
    else
        return FALSE;
}
4、求顺序栈长度
int StackLength(SeqStack S)
{
    return S.top-S.base;
}
5、清空栈
int ClearStack(SeqStack S)
{
    if(S.base)
        S.top=S.base;
    return OK;
}
6、销毁栈
int DestryStack(SeqStack &S)
{
    if(S->base)
    {
        delete S.base;
        S.stacksize=0;
        S.base=S.top=NULL;
    }
    return OK;
}
7、入栈
int Push(SeqStack *S,ElemType x)
{
    if(S->top==Stack_Size-1)
        return FALSE;
    S->top++;
    S->elem[S->top]=x;
    return TRUE;
}
8、出栈
int Pop(SeqStack *S,ElemType *x)
{
    if(S->top==-1)
        return FALSE;
    *x=S->elem[S->top];
    S->top--;
    return TRUE;
}
9、取栈顶元素
int GetTop(SeqStack *S,ElemType *x)
{
    if(S->top==-1)
        return FALSE;
    *x=S->elem[S->top];
    return TRUE;
}
五、链栈的表示和实现
  • 链栈是运算受限的单链表,只能在链表头部进行操作
typedef struct node
{
    ElemType data;
    struct node *next;
}LinkStackNode,*LinkStack;
  • 链表的头指针就是栈顶
  • 不需要头结点
  • 基本不存在栈满的情况
  • 空栈相当于头指针指向空
  • 插入和删除仅在栈顶处执行
1、链栈的初始化
void InitStack(LingkStack &S)
{
    S=NULL;
}
2、判断栈空
status StackEmpty(LinkStack S)
{
    if(S==NULL)
        return TRUE;
    else
        return FALSE;
}
3、入栈
int Push(LinkStack top,ElemType x)
{
    LinkStackNode *temp;
    temp=(LinkStackNode *)malloc(sizeof(LinkStackNode));
    if(temp==NULL)
        return FALSE;
    temp->data=x;
    temp->next=top->next;
    top->next=temp;
    return TRUE;
}
4、出栈
int Pop(LinkStack top,ElemType *x)
{
     LinkStackNode *temp;
    temp=top->next;
    if(temp==NULL)
        return FALSE;
    top->next=temp->next;
    *x=temp->data;
    free(temp);
    return TRUE;
}
5、取栈顶元素
int GetTop(LinkStack S)
{
    if(S!=NULL)
        return S->data;
}
六、栈与递归
  • 递归的定义
    • 若一个对象部分地包含它自己,或用它自己给自己定义,则称这个对象是递归的
    • 若一个过程直接地或间接地调用自己,则称这个过程是递归的过程
  • 递归问题——分治法
    • 对于一个较为复杂的问题,能够分解成几个相对简单的且解法相同或类似的子问题来求解
  • 递归的优缺点
    • 优点:结构清晰,程序易读
    • 缺点:每次调用要生成工作记录,保存状态信息,入栈;返回时要出栈,恢复状态信息。时间开销大
七、队列的表示和操作的实现
  • 顺序队列、链式队列
  • 队列的顺序表示——用一维数组base[MAXQSIZE]
#define MAXQSIZE 100  //最大队列长度
Typedef struct
{
    QElemType *base;  //初始化的动态分配存储空间
    int front;  //头指针
    int rear;   //尾指针
}sqQueue;
  • 设数组大小为MAXQSIZE rear=MAXQSIZE时,发生溢出
    • 若front=0 rear=MAXQSIZE时,再入队——真溢出
    • 若front≠0 rear=MAXQSIZE时,再入队——假溢出
顺序队列
1、队列的初始化
Status InitQueue(SqQueue &Q)
{
    Q.base=(QElemType*)malloc(MAXQSIZE*sizeof(QElemType));   //分配数组空间
    if(!Q.base)
        return(OVERFLOW);  //存储分配失败
    Q.front=Q.rear=0;    //头指针尾指针置为0,队列为空
    return OK;
}
2、求队列长度
int QueueLength(SqQueue Q)
{
    return((Q.rear-Q.front+MAXQSIZE)%MAXQSIZE);
}
3、循环队列入队
status EnQueue(SqQueue &Q,QElemType e)
{
    if((Q.rear+1)%MAXQSIZE==Q.front)
        return ERROR;     //队满
    Q.base[Q.rear]=e;     //新元素入队尾
    Q.rear=(Q.rear+1)%MAXQSIZE;  //队尾指针+1
    return OK;
}
4、循环队列出队
status DeQueue(SqQueue &Q,QElemType e)
{
    if(Q.front==Q.rear)
        return ERROR;          //队空
    e=Q.base[Q.front];         //保存队头元素
    Q.front=(Q.front+1)%MAXQSIZE;  //队头指针+1
    return OK;
}
5、取队头元素
SElemType GetHead(SqQueue Q)
{
    if(Q.front!=Q.rear)  //队列不为空
        return Q.base[Q.front];  //返回队头指针元素的值,队头指针不变
}
链式队列
#define MAXQSIZE 100
typedef struct Qnode
{
    QElemType data;
    struct Qnode *next;
}QNode,*QueuePtr;

typedef struct
{
    QueuePtr front;
    QueuePtr rear;
}LinkQueue;
1、初始化
status InitQueue(LinkQueue &Q)
{
    Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
    if(!Q.front)
        return(OVERFLOW);
    Q.front->next=NULL;
    return OK;
}
2、链队列销毁
status DestroyQueue(LinkQueue &Q)
{
    while(Q.front)
    {
        p=Q.front->next;
        free(Q.front);
        Q.front=p;
    }
    return OK;
}
3、入队
status EnQueue(LinkQueue &Q,QElemType e)
{
    p=(QueuePtr)malloc(sizeof(QNode));
    if(!p)
        return(OVERFLOW);
    p->data=e;
    p->next=NULL;
    Q.rear->next=p;
    Q.rear=p;
    return OK;
}
4、出队
status EnQueue(LinkQueue &Q,QElemType e)
{
    if(Q.front==Q.rear)
        return ERROR;
    p=Q.front->next;
    e=p->data;
    Q.front->next=p->next;
    if(Q.rear==p)
        Q.rear=Q.front;
    delete p;
    return OK;
}
5、取队头元素
Status GetHead(LinkQueue Q,QElemType &e)
{
    if(Q.front==Q.rear)
        return ERROR;
    e=Q.front->next->data;
    return OK;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值