栈和队列

栈和队列

栈和队列只在一端进行插入和删除,所以链式存储毫无优势。两者一般采用顺序存储。

特点:后进先出。常见应用:数制转化,表达式求值(后缀用一个栈。中缀用两个栈,一个存数字一个存运算符。)(左括号优先级高于括号外低于括号内的,右括号优先级低于括号内的。左右括号相遇时一起出栈)

基操:初始化,取栈顶元素,进栈,出栈

顺序栈

插入和删除均在表尾进行

结构体定义和初始化

与顺序表不同的是栈会定义一个top变量来指示栈顶元素在数组中的位置(top的初始值为-1表示空栈)。top值不能超出栈的长度。

#define MAXSIZE 20
typedef struct{
    elemtype data[MAXSIZE];
    //或是elemtype * data;
    int top;
}SqStack;
//初始化
void InitStack(SqStack *s){
  //或是  s->data=(elemtype *)malloc(MAXSIZE*sizeof(elemtype));
    s->top=-1;
}

进栈和出栈

进栈分为两步:①top加一②将元素推入栈顶

出栈的顺序与进栈相反:先将元素弹出来再top减一

//进栈
status Push(SqStack *s;elemtype e){
    if(s->top==MAXSIZE-1)//栈满
        return ERROR;
    s->top++;
    s->data[s->top]=e;
    return OK;
}
//出栈,用e返回其值
status Pop(SqStack *s;elemtype * e){
    if(s->top==-1)//栈空
        return ERROR;
    *e=data[s->top];
    s->top--;
    return OK;
}

取栈顶元素

注意要判断栈是否为空

status GetTop(SqStack s;elemtype * e){
    if(s.top==-1)
        return ERROR;
    *e=s.data[s.top];
    return OK;
}

置空顺序栈

若要将栈里的元素清空,只需令top=-1。这样后面再执行进栈操作时以前的元素便会被覆盖。

链栈

不带头节点的单链表,表头指针即栈顶指针。插入和删除在表头进行(因此采用的是头插法)。

结构体定义和初始化

建立空栈就是让表头指针指向NULL

typedef struct StackNode{
    elemtype data;
    struct StackNode * next;
}* LineStack,StackNode;
//初始化
LinkStack InitLinkStack()
{
    LinkStack  top;                    
    top = (LineStack)malloc(sizeof(StackNode));
    if(!top)
        printf("OVERFLOW\n");
    top = NULL;
    return top; 
}

进栈和出栈

进栈:先建立新结点,再将新节点后继指向原首节点。top指针再指向新节点。

出栈:先建立新节点,再将栈顶结点赋值给它。然后top指针下移一位。将那个新结点free掉

//进栈
status LinkStackPush(LinkStack top,ElemType x)
{
    LinkStack p;
    p = (StackNode *)malloc(sizeof(StackNode));    //创建一个结点 
    p->data = x;                             
    p->next = top;                                 
    top = p;                                   
    return OK;
}
//出栈
status  LinkStackPop(LinkStack top;elemtype * e)//出栈的时候必须判断是否栈空 
{
    LinkStack p;
    if(top != NULL)
    {
        e= top->data;                        //取栈顶元素,非必需 
        p = top;               
        top = top->next;
        free(p);                      
    }
    else{
         printf("stack empty!\n");
        return ERROR;
    }     
    return  OK;
} 

置空链栈

status ClearLineStack(LineStack top){
    LineStack p,q;
    p=top;
    while(p){
        q=p;
        p=p->next;
        free(q);
    }
}

队列

特点:先进先出。与栈不同的是队列 两端都是开口。删除元素的一端叫队头,称出队,插入元素的一端叫队尾,称入队。

链式队列

一条带头节点的单链表,两指针front,rear分别指向头节点和尾节点。

空队列:s->front=s->rear

结构体定义和初始化

typedef struct Qnode{
    elemtype data;
    struct Qnode * next;
}Qnode;
typedef struct{
    Qnode * front,rear;//队头队尾指针
}LinkQueue;

//初始化
status InitQueue(LinkQueue * s){
    s->front=s->rear=(LinkQueue)malloc(sizeof(Qnode));
    s->front->next=NULL;
    return OK;
}

入队和出队

入队:先将新节点的data赋值,next赋值为NULL。然后rear-next指向新节点,最后rear++

出队:注意,如果出队时除了头节点只剩一个结点则需将rear指向头节点。还要注意是否为空队。不要忘记free掉出队的结点

//入队
status EnQueue(LinkQueue *s;elemtype e){
    Qnode *p=(Qnode *)malloc(sizeof(Qnode));
    p->data=e;
    p->next=NULL;
    s->rear->next=p;
    s->rear=p;
    return OK;
}
//出队
status DeQueue(LinkQueue *s;elemtype *e){
    Qnode *q;
    if(s->front==s->rear)
        return ERROR;
    q=s->front->next;
    *e=q->data;
    s->front->next=q->next;
    if(s->rear=q)
        s->rear=s->front;
    free(q);
    return OK;
}

顺序队列

建立front和rear两个标志变量,其值是队头和队尾元素所在的数组下标。(开始时front=rear=0)(rear指向队尾元素的下一个位置)

入队时将元素存储在rear所指的位置后rear++。出队时front++即可

typedef struct{
    elemtype data[MAXSIZE];
    int front;
    int rear;
}SqQueue
    //初始化就是front=rear=0

循环队列

循环队列的存储结构也是顺序表,为了解决顺序队列可能产生假溢出的情况,我们一般都用循环队列代替顺序队列。

解决假溢出的办法就是后面满了,就再从头开始,也就是头尾相接的循环顺序存储结构。

但是这样做会产生一个问题:当front=rear时既可以表示队列空也可以表示队列满。为了解决这个问题可以采取一种方法:规定保留一个存储空间,当队列满时数组还有一个闲置空间。

于是:①队空:front=rear ②队满:(rear+1)%MAXSIZE=front ③入队:rear=(rear+1)%MAXSIZE ④出队:front=(front+1)%MAXSIZE ⑥求实际长度:(rear-front+MAXSIZE)%MAXSIZE

入队和出队

//入队
status EnQueue(SqQueue *s;elemtype e){
    if((s->rear+1)%MAXSIZE==front)//判断队满
        return ERROR;
    s->data[s->rear]=e;
    s->rear=(s->rear+1)%MAXSIZE;
    return OK;
}
//出队
status DeQueue(SqQueue *s;elemtype *e){
    if(s->front==s->rear)//判断队空
        return ERROR;
    *e=s->data[s->front];
    s->front=(s->front+1)%MAXSIZE;
    return OK;
}

置空顺序/循环队列只需令front=rear=0。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值