数据结构第三章 栈和队列

前言:

        栈和队列可以称为操作受限的线性表。

目录:

一、栈

     1.栈的定义

     2.栈的表示和实现

        ①  顺序栈

        ②双向栈

       ③链栈

二、队列

     1.队列的定义

    2.队列的表示和实现

        ①循环队列


一、栈

     1.栈的定义

        限定仅在表尾进行插入和删除的线性表。表尾端称为栈顶 (top),表顶端称为栈底 (bottom)。a1称为栈底元素,an称为栈顶元素。
        如图所示,我们不难看出:栈是一个“
后进先出,先进后出”的线性表。

         注:栈除了存储数据元素外,还记录了数据元素入栈的次序。(考试必考点)
例:现有元素a、b、c、d、e、f 依次进栈,允许出栈、退栈操作交替进行。但不允许连续三次进行退栈操作,则不可能得到的出栈序列是:
        A. dcebfa        B. cbdaef        C. bcaefd       
D.afedcb
解析:D选项中当 f 入栈前有 bcde 依次出栈,超过了限定条件连续三次退栈操作。

     2.栈的表示和实现

        ①  顺序栈

//顺序栈的定义
typedef char SElemType;    //这里char根据具体变量类型进行更改
#define STACK_INIT_SIZE 100;
#define STACKINCREMENT 10;
typedef struct {
    SElemType *base;    //栈底指针
    SElemType *top;     //栈顶指针
    int stacksize;      //存储容量
} SqStack;

//顺序栈的初始化
#define OVERFLOW -1;
void InitStack(SqStack *S)
{
    S->base = (SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
    if(!S->basse){    //分配空间失败,则进行报错并结束程序
        printf("分配空间失败!");
        exit(OVERFLOW);
    }
    S->top = S->base;
    S->stacksize = STACK_INIT_SIZE;
}

//顺序栈的入栈操作
void Push(SqStack *S, SElemType e)
{
    if((S->top - S->base) >= S->stacksize){    //栈满判定    
        S->base = (SElemType *)realloc(S->base,
             (S->stacksize+STACKINCREMENT)*sizeof(SElemType));
        if(!S->basse){    //分配空间失败,则进行报错并结束程序
            printf("分配空间失败!");
            exit(OVERFLOW);
        }
        S->top = S->base + S->stacksize;
        S->stacksize = S->stacksize + STACKINCREMENT; 
    }
    *S->top++ = e;
}

//顺序栈的出栈操作
void Pop(SqStack *S, SElemType *e)
{
    if(S->top == S->base){
        printf("栈空!");
        return -1;
    }
    *e = *--S->top;
}

        栈底指针指向分配空间的第一个单元,栈顶指针指向栈顶元素后的一个单元
       
上溢:当栈满时再做入栈运算必定产生空间溢出;
       
下溢:当栈空时再做出栈运算也将产生溢出。

        ②双向栈

        在一个程序中同时使用两个数据类型相同的栈,可以考虑采用双向栈。

//双向栈的定义
#define STACKSIZE 100;
typedef char SElemType;
typedef struct {
    int top[2];        //栈顶指针
    SElemType *base;   //存储基址
    int stacksize;
}DqStack;

//双向栈的初始化
void InitStack(DqStack *S)
{
    S->top[0] = -1;
    S->top[1] = STACKSIZE;
    S->stacksize = STACKSIZE;
    S->base = (SELemType *)malloc(STACKSIZE*sizeof(SElemType));
}

//双向栈的进栈操作
#define ERROR -1
void Push(DqStack *S, int e, int i)     //进i号栈
{
    if(S->top[1] - S->top[0] == 1){
        printf("栈满!");
        return ERROR;
    }
    switch(i){
        case 0:
            ++S->top[0];
            S->base[S->top[0]] = e;
            break;
        case 1:
            --S->top[1];
            S->base[S->top[1]] = e;
            break;
        default:
            break;
    }
}

//双向栈的出栈操作
#define ERROR -1;
void Pop(DqStack *S, int *e, int i)     //出i号栈
{
    switch(i){
        case 0:
            if(S->top[0] == -1){
                printf("栈空!");
                return ERROR;
            }
            *e = S->base[--S->top[0]];
            break;
        case 1:
            if(S->top[1] == STACKSIZE){
                printf("栈空!");
                return ERROR;
            }
            *e = S->base[++S->top[1]];
            break;
        default:
            break;
    }
}


       ③链栈

//链栈的定义
typedef struct SNode{
    SElemType data;
    struct SNode *next;
} *LinkStack;

二、队列

     1.队列的定义

        限定在表的一端进行插入,在表的另一端进行删除的线性表。表插入端称为队尾;表删除端称为队头。a1称为队头元素,an称为队尾元素。
        如图所示,我们不难看出:队列是一个“
先进先出,后进后出”的线性表

        注:跟栈一样,我们仍然可以从队列中得到元素的入队次序。(考试必考点)
例:某队列允许在两端进行入队操作,但仅允许在一端进行出队操作,若元素a,b,c,d,e依次入队列后再进行出队列,则不可能得到出对序列是:
        A. bacde         B. dbace       
C. dbcae        D. ecbad

    2.队列的表示和实现

        ①循环队列

//循环队列的定义
typedef char QElemType;
#define MAXQSIZE 100
typedef struct {
    QElemType *base;    //存储基址
    int front;          //头指针
    int rear;           //尾指针
} SqQueue;

//循环队列的初始化
#define OVERFLOW -1;
void InitQueue(SqQueue *Q)
{
    Q->base = (QElemType *)malloc(MAXQSIZE*sizeof(QElemType));
    if(!Q->base){
        printf("分配空间失败!");
        exit(OVERFLOW);
    }
    Q->front = Q->rear = 0;
}

//循环队列的入队操作
#define ERROR -1;
void EnQueue(SqQueue *Q, QElemType e)
{
    if((Q->rear+1)%MAXQSIZE == Q->front){
        printf("队满!");
        return ERROR;
    }
    Q->base[Q->rear] = e;
    Q->rear = (Q->rear+1) % MAXQSIZE;
}

//循环队列的出队操作
void DeQueue(SqQueue *Q, QElemType *e)
{
    if(Q->front == Q->rear){
        printf("队空!");
        return ERROR;
    }
    *e = Q->base[Q->front];
    Q->front = (Q->front + 1) % MAXQSIZE;
} 

        ②链栈

//链队的定义
typedef char QElemType;
typedef struct QNode {
    QElemType data;        //数据域
    struct QNode *next;    //指针域
} QNode, *QueuePtr;
typedef struct {
    QueuePtr front;    //队头指针
    QueuePtr rear;     //队尾指针
} LinkQueue;

//链队的初始化
#defint OVERFLOW -1;
void InitQueue(LinkQueue *Q)
{
    Q->front = Q->rear = (QueuePtr)malloc(sizeof(QNode));
    if(!Q->front){
        printf("分配空间失败!");
        exit(OVERFLOW);
    }
    Q->front->next = NULL;
}

//链队的入队操作
void EnQueue(LinkQueue *Q, QElemType e)
{
    QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
    if(!p){
        printf("分配空间失败!");
        exit(OVERFLOW);
    }
    p->data = e;
    p->next = NULL;
    Q->rear->next = p;
    Q->rear = p;
}

//链队的出队操作
#define ERROR -1;
void DeQueue(LinkQueue *Q, QElemType *e)
{
    if(Q->rear == Q->front){
        printf("队空!");
        return ERROR;
    }
    QueuePtr p = Q->front->next;
    *e = p->data;
    Q->front->next = p->next;
    if(Q->rear ==p) Q->rear = Q->front;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱睡觉的panda

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值