栈队列

Posted suizhixxie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了栈队列相关的知识,希望对你有一定的参考价值。

栈和队列也都是线性表,是操作受限的特殊线性表

栈 :先进后出

顺序栈:假设有一个足够大的存储空间data,用于存储栈中的元素,将栈中的元素依次存储到数组中--顺序存储方式--顺序栈。其中设置一个整形变量top,指示栈顶,即栈顶元素的数组下标,也可用来计数元素个数 将数组 data和top作为顺序栈的数据成员。

技术图片

#include <iostream>
#define MAXLEN 100
typedef int elementType;
//顺序栈存储定义
typedef struct sStack{
    elementType data[MAXLEN];//定义一个足够大的数组
    int top;//指示栈顶
}seqStack;//顺序栈定义  
//栈初始化
void initialStack(seqStack &s){
    s.top = -1;
}

//判断栈空
bool stackempty(seqStack &s)
{
    if (s.top == -1)
        return true;
    return false;
}//简写 return(s.top == -1);
//判断栈满
bool stackfull(seqStack &s)
{
    if (s.top == MAXLEN-1)
        return true;
    return false
}
//取栈顶元素
bool getTop(seqStack &s,elementType &x){
    if(stackempty){
        return false;
    }
    else{
        x = s.data[s.top];
        return true;
    }
}

//入栈
bool push(seqStack &s,elementType x){
    if (stackfull)
        return false
    else{
        s.top++;//增加栈顶 
        s.data[s.top] = x;//数据入栈
        return true;
    }
}

//出栈
bool pop(seqStack &s, elementType &x){
    if (stackempty){
        return false
    }
    else{
        x = s.data[s.top];
        top--;
        return true;
    }
}

 顺序栈特点:所有运算的时间复杂度均为O(1);通常一次性申请空间,只能按最大空间需求分配,容易造成空间浪费(可以使用链式栈代替顺序栈)

链栈  采用链式存储结构实现的栈,可以用单链表结构来表示,结点结构同单链表 链栈可以带头结点,也可以不带头结点。不带头节点栈顶指针top指示首元素节点,带头结点,栈顶指针top->next指示首元素节点

技术图片

typedef int elementType;  //elementType 定义为整数类型

typedef struct lsNode
{
    elementType data;     //链栈结点数据域
    struct lsNode *next;  //链栈结点指针域
} node,*linkedStack;
//使后面使用node *top 或 linkedStack top都行

//初始化栈 不带头结点
void initialStack(node *&top)
{
    top=NULL;//将栈顶指针置空
}

//判定栈空
bool stackEmpty(node* top)
{
    if(top==NULL)
        return true;  //栈空,返回true
    else
        return false;   //栈不空,返回false
}

//取栈顶元素
bool getTop(node * top, elementType &x)
{
    if(top==NULL)
        return false;  //栈空,返回false
    else
    {
        x=top->data;   //取栈顶元素,用参数x返回
        return true;   //取栈顶成功,返回true
    }
}


//入栈
void push(node *& top, elementType x)
{
    node* s;
    
    s=new node;
    s->data=x;
    s->next=top;
    top=s;

}

//出栈
bool pop(node *& top, elementType &x)
{
    node* u;
    if(top==NULL)
        return false;   //栈空,返回false
    else
    {
        x=top->data;    //取栈顶元素,由变量x返回
        u=top;          //栈顶指针保存到u
        top=top->next;  //栈顶指针后移一个元素结点
        delete u;       //释放原栈顶结点
        return true;    //出栈成功,返回true
    }
}

void destroyStack(node *& top)
{
    node *p,*u;
    p=top;
    while(p)
    {
        u=p;
        p=p->next;
        delete(u);        
    }
    top=NULL;
}

//交互循环压入元素
void createLinkedStack(linkedStack &top)
{        
    elementType x;
    node *p;    
    cout<<"请输入数据元素(整数,-9999退出):"<<endl;
    cout<<"x=";
    cin>>x;
    while(x!=-9999)   //非结束符,循环入栈
    {
        p=new node;
        p->data=x;

        p->next=top;
        top=p;

        cout<<"x=";
        cin>>x;
    }
}


 

 链式栈特点:使用连续或不连续的存储空间,各数据元素独立存储,依靠指针连接建立逻辑相邻关系,对每个数据元素单独申请结点空间,没有栈满溢出的情况,栈顶指针top唯一确定一个链式栈。

 逆置单链表:

1、从原链表首元素节点依次取出放入新表即可  头插法

void reverse(linkedStack & l)
{
    node *p,*s;
    p = l ->next;
    l->next = NULL;
    while(p)
    {
        s = p;
        p = p->next; //利用s中转 
        s->next = l->next;
        l->next = s
    }

}

 

 2、定义一个顺序栈,循环每个节点指针入栈,首元素节点指针在栈底,将栈内节点依次弹出按尾插法来重建链表。

void reverse(linkedStack & l){
    SeqStack S;
    initialStack(S);
    node* p ;
    p = l->next;
    while(p){
        
        S.push(p);
        p = p->next;
    }
    l->next = NULL;
    while(!stackEmpty(S)){
        p = S.pop();
        l->next = p;
    }
    l->next = NULL
}

 队列 也是线性表,插入和删除只能在一端进行。

 技术图片

普通队列随着删除、插入的进行容易造成假溢出

循环队列

技术图片

#define MAXLEN 100
typedef int elementType;
//根据函数接收参数的不同 引用传值还是指针传值   用.给变量赋值  -> 指针赋值
typedef struct squeue
{
    elementType data[MAXLEN];
    int front,rear;
}seqQueue;

void initial(seqQueue * Q)
{
    Q->front = 0;
    Q->rear = 0;
}
bool isEmpty(seqQueue & Q)
{
    if (Q.front == Q.rear)
        return true;
    return false;
}
bool isFull(seqQueue & Q)
{
    if ((Q.rear+1)%MAXLEN == Q.front)
        return true;
    else 
        return false;
}
bool getFront(seqQueue &Q,elementType &x)
{
    if isEmpty(Q)
        return false;
    else:
        x = Q.data[[Q.front+1] %MAXLEN]
    }
bool enQueue(seqQueue &Q , elementType x)
{
    if (isFull(Q))
        return false;
    else
        Q.rear = (Q.rear+1)%MAXLEN;
        Q.data[Q.rear] = x;
        return true;
}
bool outQueue(seqQueue &Q, elementType &x)
{
    if (isEmpty(Q))
        return false;
    else 
        Q.front = (Q.front+1)%MAXLEN;
          x = Q.data[Q.front];
          return true;
}

 队列的应用   杨辉三角

 技术图片

void yanghuiTriangle(int n)
{
    seqQueue Q;
    initial(&Q)
    int s1,s2,x;
    cout << 1<<endl;
    enQueue(&Q ,1)
    for (int i = 2; i <= n; i++)
    {
        s1 = 0;
        for (int j = 1; j <= i-1; j++)
        {
            getFront(Q,s2);
            outQueue(&Q,x);
            cout << s1+s2 <<"	";
            enQueue(&Q, s1+s2);  每次保证队列中是上一行的元素 在遍历队列依次相加 得到下一行元素
            s1 = s2;        
        }
        cout << 1<<endl;
        enQueue(&Q,1);
    }
}

 

 链队列  节点结构和单链表相同,需要两个指针分别指向队头和队尾。

 技术图片

typedef int elementType;
typedef struct Node
{
    elementType data;
    struct Node *next;
}node;
typedef struct queue
{
    node *front;
    node *rear;    
}linkedQueue;
void initial(linkedQueue &Q){
    Q.front = new node;
    Q.rear = Q.front;
    Q.front->next = NULL;
}
bool isempty(linkedQueue &Q){
    if (Q.rear == Q.front)
        return true;
    else
        return false;
}
bool getFront(linkedQueue &Q,elementType &x)
{
    if (isempty(Q))
    {
        return false;/* code */
    }
    x =( (Q.front)->next)->data;
    return true;
}
void enQueue(linkedQueue &Q,elementType x)
{
    node* p = new node;
    p->data = x;
    p->next = NULL;
    Q.rear ->next =  p;
    Q.rear = p;
}
bool outQueue(linkedQueue &Q,elementType &x)
{
    if (isempty(Q))
    {
        return false;/* code */
    }
    node *p = new node;
    p = Q.front->next;
    x = p->data;
    Q.front->next = p->next;
    delete(p);
    if (Q.front->next == NULL )//只有一个节点时
        Q.rear = Q.front;
    return true
}
void destory(linkedQueue &Q){
    node *p,*u;
    p = Q.front;
    while(p){
        u = p;
        p = p->next;
        delete(u);
    }
    Q.front = NULL;
    Q.rear =NULL;
}

 

以上是关于栈队列的主要内容,如果未能解决你的问题,请参考以下文章

用两个队列实现一个栈and用两个栈实现一个队列

数据结构栈队列相关代码(数据结构笔试复测Leecode牛客)

数据结构栈与队列

数据结构栈与队列

栈和队列基本操作

代码随想录算法训练营第10天 | ● 理论基础 ● 232.用栈实现队列 ● 225. 用队列实现栈