数据结构第三章栈和队列

本文详细介绍了数据结构中的栈和队列概念,包括顺序栈、链栈、循环队列和链队的定义、初始化、入栈、出栈、取栈顶元素等操作。同时,探讨了循环队列解决假溢出问题的机制,并讲解了链队的实现。此外,还提到了双端队列在特定场景下的应用。
摘要由CSDN通过智能技术生成

第三章栈和队列

3.1栈(Stack)

是只允许在一端进行插入或者删除操作的线性表

特点:先进后出 Last in First out(LIFO)

顺序栈

定义与初始化
//顺序栈的定义
#define MaxSize[10]
typedef struct{
    ElemType data[MaxSize];
    int top;
}SqStack;


//初始化栈
bool InitStack(SqStack &S){//初始化栈顶指针
    S.top=-1;//这里面top指向的栈顶元素,如果top的初始值是0,那么top指向的就是栈顶元素的下一个元素
}

//栈的判空
bool StackEmpty(SqStack S){
    return(top=-1);
}
void testStack(){
    SqStacck S;//先声明再使用
    InitStack(&S);
}
进栈Push
bool Push(SqStack &S,ElemType e){
    if(S.top==MaxSize-1)//栈满
        return false;
    S.top=S.top+1;
    S.data[top]=e;
    return true;
}
出栈Pop
bool Pop(SqStack &S,ElemType e){
    if(S.top==-1)
        return false;
    e=S.data[S.top];
    S.top=S.top-1;
    return true;
}
读栈顶元素
bool GetTop(SqStack S,ElemType &e){
    if(S.top==-1)
        return false;
    e=S.data[S.top];
    return true;
}
共享栈
define MaxSize 10//共享栈的定义
tyepdef struct{
    ElemType data[MaxSize];
    int top0;
    int top1;
}

bool InitStack(){
    top0=-1;
    top1=MaxSize;
}

//栈满的条件是top0+1=top1;

链栈

定义与初始化
typedef struct StrackNode{//栈的定义
    ElemType data;
    struct StrackNode *next;
}StrackNode,*LinkStrack;
入栈
bool Push(LinkStrack &S,ElemType e){
    p=new StrackNode;
    p->data=e;
    p->next=S;
    S=p;
    return true;
    
}
出栈
bool Pop(LinkStrack &S,ElemType e){
    if(S==null)
        return false;
    e=S->data;
    StrackNode *p;
    p=S;
    S=S->next;
    delete p;
    return true;
}
取栈顶元素
bool GetTop(LinkStrack S,ElemType e){
    if(S==null)
        return null;
    e=S->data;
    return true;
}

3.2队列

一端2插入一端删除的线性表。First in First out (FIFO)

循环队列(顺序实现)

为什么要实现循环的队列呢,其实主要原因是会出现假溢出的现象,如下图所示

1234

队头 队尾

此时由于队尾不能再继续插入元素,再插入元素就会出现数组下标越界的情况,但是队头却是空的,由此会出现假溢出的现象,此时使用循环队列就会十分恰当。

定义与初始化
dedine MaxSize 10//队列的定义
typedef struct{
    ElemType data[MaxSize];
    int front;
    int rear;
}SqQueue;

bool InitQueue(SqQueue &Q){
    Q.front=Q.rear=0//注意,这里面rear指向的队尾元素的下一个元素,若是定义的时候,rear=MaxSize-1;此时,rear表示的是队尾元素,下面都采用rear表示队尾元素的下一个元素
}
入队
bool EnQueue(SqQueue &Q,ElemType e){
    if((Qrear+1)%MaxSize==Q.front)
        return false;
    Q.data[Q.rear]=e;
    Q.rear=(Q.rear+1)%MaxSize;
    return ture;
}
出队
bool DeQueue(SqQueue &Q,ElemType e){
    if(Q.front==Q.rear)
        return false;
    e=Q.data[Q.front];
    Q.front=(Q.front+1)%MaxSize;
    return true;
}
判断队列已满/已空
bool QueueEnough(SqQueue &Q){//判断队列已满
    return (Q.rear+1)%MaxSize==Q.front;
}


bool QueueEmpty(SqQueue &Q){//判断队列已空
    return Q.front==Q.rear;
}
取队首元素
bool GetFront(SqQueue &Q,ElemType e){
    if(Q.front==Q.rear)
        return false;
    e=Q.data[Q.front];
    return true;
}
不准浪费队列存储空间

其实上面所采用的方法是空出一个存储空间,来区分队列已满还是已空,假如出试卷的老师要求我们不准浪费存储空间,又该如何答题呢

  • 在定义队列的时候加上一个size变量,用来表示当前队列中的元素个数,当size=0,则表示空。当size=MaxSize,则表示满
  • 当队列空的时候,那么队列上一次进行的操作一定是出队,反之满的时候应当是入队。那么在定义队列的时候,可以加上一个tag变量,当进行出队操作的时候tag=0,当入对的时候tag=1,即frontrear&&tag0就表示空,frontrear&&tag1就表示满

链队

定义与初始化
 typedef struct QNode{//链表的初始化
     Elemtype data;
     struct QNode *next;
 }QNode,*QueuePtr;
typedef struct{
    QueuePtr front;
    QueuePtr rear;
}LinkQueue;


//初始化
bool InitQueue(LinkQueue &Q,ElemType e){//带头结点
    Q.front=Q.rear=new QNode;
    Q.front->next=null;
    return true;
}

bool InitQueue(LinkQueue &Q,ElemType e){//不带头结点
    Q.front=Q.rear=null;
    return true;
}
入队
bool enqueue(LinkQueue &Q,ElemType e){//带头结点
    p=new QNode;
    p->data=e;
    p->next=null;
    Q.rear->next=p;
    Q.rear=p;
    return true;
}

bool enqueue(LinkQueue &Q,ElemType e){//不带头结点
    p=new QNode;
    p->data=e;
    p->next=null;
    if(Q.front==Q.rear){
        Q.front=p;
        Q.rear=p;
         return true;
    }
    else{
        Q.rear->next=p;
        Q.rear=p;
         return true;
    }
    
   
}
出队
bool DuQueue(LinkQueue &Q,ElemType &e{//带头结点
    if(Q.front==Q.rear)
        return false;
    e=Q.front->next-data;
    LNode *p;
    p=Q.front->next;
    Q.front->next=p->next;
    if(p==Q.rear)
        Q.front=Q.rear;
    free (p);
    return true;
}
 
             
bool DuQueue(LinkQueue &Q,ElemType &e{//不带头结点
    if(Q.front==Q.rear)
        return false;
    LNode *p;
    p=Q.front;
    e=p->data;
    Q.front=p->next;
    if(p==Q.rear)
        Q.front=Q.rear=null;
    free (p);
    return true;
}            
取队头元素
bool GetTop(LinkQueue Q,ElemType e){//带头结点
    if(Q.front==Q.rear)
        return false;
    e=Q.front->next->data;
    return true;
}

bool GetTop(LinkQueue Q,ElemType e){//不带头结点
    if(Q.front==Q.rear)
        return false;
    e=Q.front->data;
    return true;
}
双端队列

其实有一类题目考察的是输出序列合法性的

  • 栈:先进后出 队:先进先出 很容易
  • 输入受限的双端队列:两端可以删除,一端能插入,也比较容易写
    Q,ElemType e){//带头结点
    if(Q.front==Q.rear)
    return false;
    e=Q.front->next->data;
    return true;
    }

bool GetTop(LinkQueue Q,ElemType e){//不带头结点
if(Q.front==Q.rear)
return false;
e=Q.front->data;
return true;
}




#### 双端队列

其实有一类题目考察的是输出序列合法性的

- 栈:先进后出   队:先进先出   很容易
- 输入受限的双端队列:两端可以删除,一端能插入,也比较容易写
- 输出受限的双端队列:两端都可以插入,一端能删除,由于两个口都可以插入元素,所以要根据输出结果把比当前数字及以后的数逆序(一直到比当前数字大,或者数结束为止),然后看看能不能得到这样的输入,能得到就继续判断,一直到所有数字判断结束。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值