数据结构___栈和队列的学习总结

概要

因为操作的需要现在重新学习了数据结构相关知识,故以此文来总结一下栈和队列的操作和基本知识 

声明:因个人能力有限,本文仅是个人的学习记录笔记,有错误之处还望指出

栈和队列的基本概念和实现

1.栈的基本概念

  • 栈的定义:栈是一种只能在一端进行插入和删除的线性表。其中允许进行插入和删除的一端称为栈顶
  • 栈的特点:先进后出(FILO)
  • 栈的存储结构:顺序栈和链式栈,实际上栈的本质是线性表,不过是加了操作限制

2.队列的基本概念

  • 队列的定义:和栈类似都是操作受限制的线性表,只允许在一端进行插入(队尾:rear),在一端进行删除(队头:front);
  • 队列的特点:先进先出(FIFO)
  • 栈的存储结构:顺序队和链式队

栈和队列的存储结构和算法应用

1.顺序栈的定义

typedef struct {
    int data[MAXSIZE];          //存放的数据
    int top;                    //栈顶指针
}SqStack;

2.链栈结点定义

typedef struct LNode{
    int data;
    struct LNode *next;
}LNode;

3.顺序队列的定义

typedef struct {
    int data;       //数据域
    int front;      //队头指针
    int rear;       //队尾指针
}SqQueue;

4.链队的定义

//队结点的定义
typedef struct QNode{
    int data;       //数据域
    struct QNode *next; 
}QNode;

//链队类型的定义
typedef struct QNode{
    QNode *rear;        //队尾指针
    QNode *front;       //队头指针
}LiQueue;


5.顺序栈的基本操作
顺序栈有四要素:两个特殊状态(栈满\栈空),两个操作(入栈\出栈)

  • 栈空的状态:
st.top == -1
  • 栈满的状态:
//因为栈是特殊数组,元素下标从0开始
st.top == MAXSIZE-1
  • 入栈操作:
//要先操作栈顶指针,再赋值
++(st.top);
st.data[st.top]=x;
//或者
st[++top]=x;
  • 出栈操作:
//先读取数据再操作栈顶指针
x=st.data[st.top];
--(st.top);
//或者
x=st[top--];
  • 初始化栈
void InitStack(SqStack &st){
st.top==-1;
}
  • 判断栈为空
bool IsEmpty(const SqStack st){
    if(st.top == -1)
        return ture;
    return false;
}
  • 进栈
bool push( SqStack &st,int x){
    //判断栈是否未满
    if(st.top == MAXSIZE-1)
        return false;
    else{
        ++(st.top);
        st.data[st.top]=x;
        return true;
    }
}
  • 出栈
//对数据进行改变的要传入地址
bool pop( SqStack &st,int &x){
    //判断栈是否为空
    if(st.top == -1)
        return false;
    else{
        x=st[top];
        --(st.top);
        return true;
    }
}

6.链栈的基本操作
链表栈有四要素:两个特殊状态(栈满\栈空),两个操作(入栈\出栈)

  • 初始化链栈
void InitStack(Lnode *lst){
    lst=(Lnode *)malloc(sizeof(Lnode));
    lst->next=NULL;
}
  • 判断链栈为空
bool IsEmpty(const LNode *st){
    if(lst->next==NULL)
        return ture;
    return false;
}
  • 进栈
void push( LNode *st,int x){
   LNode *p;        //新建结点
   p=(LNode)malloc(sizeof(LNode));
   p->next=NULL;
   
   //头插法插入
    p->data=x;
    p->next=st->next;
    st->next=p;
}
  • 出栈
//对数据进行改变的要传入地址
bool pop( LNode *st,int &x){
    //栈空不能出栈
    if(st->next ==NULL)
        return fasle;
    else{
            Lnode *p;
            p=st->next;
            x=p->data;
            st->next=p->next;
            free(p);
            return true;        
    }
}
  • 顺序栈的应用
//利用顺序栈来判断字符数组exp中的()是否成对,其中字符个数为n
bool IsMatch(char exp[],int n){
    //初始化链表
    char statck[maxsize];
    int i,top = -1;
    //遍历寻找(
    for(i=0;i<n;i++){
        if(exp[i]=='(')        //入栈
            statck[++top]='(';
        if(exp[i]==')'){
            //栈空不匹配
            if(top == -1)
                return false;
            else               //出栈
                    --top;
        }
    }
    //最后判断,如果栈空,则成对
    if(top == -1)
        return ture;
    else
        return false;
}

7.顺序队的基本操作
顺序队有四要素:两个特殊状态(队满\队空),两个操作(入队\出队)

  • 初始化顺序队
void initqueue(Squeue &qu){
    qu.rear=qu.rear=0;          //队首和队尾指针重合,指向0
}
  • 判断顺序队为满
void queueisFull(Squeue qu){
    if((qu.rear+1)%maxsize==qu.front)
        return ture;
    else
        return false;
}
  • 进队
int enQueue(Squeue &qu,int x){
    if((qu.rear+1)%maxsize==qu.front)       //如果队列为满则不能入队
        return 0;   
    qu.rear=(qu.rear+1)%maxsize;            //如果队列未满,则先移动指针
    qu.data[qu.rear]=x; 
    return 1;
}
  • 出队
int deQueue(Squeue &qu,int &x){
    if(qu.rear==qu.front)       //如果队列为空则不能出
        return 0;   
    qu.front=(qu.front+1)%maxsize;            //如果队列非空,则先移动指针
    x=qu.data[qu.front]; 
    return 1;
}

7.链队的基本操作
顺序队有四要素:两个特殊状态(队满\队空),两个操作(入队\出队)

  • 初始化链队
void initQueue(LiQueue *qu){
    qu=(LiQueue*)malloc(sizeof(LiQueue));
    qu->rear=qu->rear=NULL;
}
  • 判断链队为空
bool QueueIsEmpty(LiQueue *qu){
    if((qu->rear==NULL)||qu->rear=NULL)
        return true;
    else
        return false;
}
  • 入队算法
void EnQueue(LiQueue *qu,int x){
    LiQueue *p;
    p=(LiQueue *)malloc(sizeof(LiQueue));
    p->data = x;
    p->next=NULL;
    //如果链表为空则新节点为队首结点(也是队尾结点)
    if(qu.rear==qu.front=NULL)
        qu->front=qu->rear=p;
    else{
        qu->rear->next=p;
        qu->rear=p;
    }
}
  • 出队算法
int EnQueue(LiQueue *qu,int &x){
    LiQueue *p;         //删除的结点,要释放内存

    //如果链表为空不能出队
    if(qu.rear==qu.front=NULL)
        return 0;
    else
        p=qu->front;
    
    //队列中只有一个结点的时候
    if(qu->rear=qu->front)
        qu.rear==qu.front=NULL;
    else
        qu->front=qu->front->next;
    x=p->data;
    free(p);
    return 1;
}

应用案例

1.利用两个栈来实现队列的功能
栈的特点是先进后出,队列的特点是先进先出。故当有两个栈S1,S2来模拟队列的时候,可以将S1用作数据的输入,入栈操作,要将数据输出的时候将S1的数据入栈到S2,故栈底元素变成栈顶元素,所以先进先出也就实现了。

具体实现

#define MaxSize  100

//栈定义
typedef struct {
    int top;
    int data[MaxSize];
}stack;

//判断栈是否为空
int isEmpty(stack s){
    if(s.top == -1)
        return 1
    else
        return 0
}

//入栈
int push(stack s,int x){
    if(s.top == MaxSize -1)
        return 0
    else{
        s.data[++s.top]=x;
    }
    return 1;
}

//出栈
int pop(stack s,int &x){
    if(isEmpty(s))
        return 0
    else{
        x=s.data[s.top--];
        return 1;
    }
}

//判断队列是否为空
//两个栈都为空:队列为空
int IsQueueEmpty(stack s1,stack s2){
    if(s1.top != -1 && s2.top != -1)
        return 0
    else
        return 1
}



//入队操作
int enQueue(stack s1,stack s2,int x){
    int temp;
    //s1负责入队操作,故先判断s1里面的数据是否为满
    if(s1.top == MaxSize -1){
        if(!isEmpty(s2))
            return 0;               //s1满s2非空,不能入栈
        else if(isEmpty(s2)){
            while(!isEmpty(s1)){      //循环将s1数据放入s2
                pop(s1,temp);
                push(s2,temp);
            }     
            push(s1,x);             //x入栈实现了元素入队
            return 1}
    }
   else{
       push(s1,x);          //s1未满直接入s1
       return 1;
   }
    
}

//出队操作
int deQueue(stack s1,stack s2,int &x){
    //s2栈顶元素退栈,实现出队操作,x接收出队元素
    int temp;
    //s2不为空直接出队
    if(!isEmpty(s2)){
        push(s2,x);
    }else{
        if(isEmpty(s1)){        //输入栈也为空
            return 0;
        }
        else{
            while(isEmpty(s1)){
                pop(s1,y);
                push(s2,y);
            }
            pop(s2,x);
            return 1;
        }
    }
}



而塞过 2021-3-26

关于我:一个就要进入互联网,经历社会毒打的99小伙

下一站(javascript)
下一站(html)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值