Study notes: Big talk data structure-stack

Big talk data structure-stack

Definition of stack

A stack is a linear table that only inserts and deletes at the end of the table. One end that allows insertion and deletion is called the top of the stack, and the other end is called the bottom

  • Stack is also called last-in-first-out linear table, referred to as LIFO structure
  • The insertion operation of the stack is pushing and pushing into the stack; the deleting operation of the stack is popping
typedef int SElemType; /*SElemType类型根据实际情况而定,这里假设为int*/
typedef struct
{
    
    
    SElemType data[MAXSIZE];
    int top; /*空栈top=-1,栈满etc*/
}SqStack;

Sequential storage structure of the stack

/*进栈操作 插入元素e为新的栈顶元素*/
Status Push(SqStack *S,SElemType e)
{
    
    
    if(S->top == MAXSIZE -1) /*栈满*/
    {
    
    
        return ERROR;
    }
    S->top++; /*栈顶指针增加一*/
    S->data[S->top] = e; /*将新插入元素赋值给栈顶空间*/
    return OK;
}
/*出栈操作:若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR*/
Status Pop(SqStack *S,SElemType *e)
{
    
    
    if(S->top == -1)
        return ERROR;
    *e=S->data[S->top]; /*将要删除的栈顶元素赋值给e*/
    S->top--; /*栈顶指针减一*/
    return OK;
}

Two-stack shared space-use an array to store two stacks

  1. Design techniques for the same type of stack
  2. top1+1==top2 (stack full); stack 1 is empty stack, top2=0, stack 2 is full; stack 2 is empty stack, top1 of stack 1 is n-1, and stack 1 is full.
/*两栈共享空间结构*/
typedef struct
{
    
    
    SElemType data[MAXSIZE];
    int top1; /*栈1栈顶指针*/
    int top2; /*栈2栈顶指针*/
}SqDoubleStack;

Status Push(SqDoubleStack *S,SElemType e, int stacklNumber)
{
    
    
    if(S->top1+1==S->top2) /*栈满*/
        return ERROR;
/* ****自增、自减
* ++i/--i, i自增/减1后再参与其他的运算;i++/i--,i参与运算后,i的值域再自增/减1*/
    if(stacklNumber==1)  /*若栈1有元素进栈*/
        S->data[++S->top1] = e; /*若栈1给top1+1后给数组元素赋值*/
    else if (stacklNumber ==2)/*若栈2有元素进栈*/
        S->data[--S->top2]=e; /*若栈2给top2-1后给数组元素赋值*/
    return OK;
}
/*若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR*/
Status Pop(SqDoubleStack *S,SElemType *e, int stackNumber)
{
    
    
    if (stackNumber == 1) {
    
    
        if (S->top1 == -1)  /*空栈,溢出*/
            return ERROR;
        *e = S->data[S->top1--]; /*栈1的栈顶元素出栈*/
    }
    if (stackNumber == 2)
    {
    
    
        if(S->top2==MAXSIZE)  /*空栈,溢出*/
            return ERROR;
        *e = S->data[S->top2++]; /*栈2的栈顶元素出栈*/
//        data[s--]等价于data[s];s--;
//        data[++s]等价于++s;data[s];
//        data[++s],++s入栈;先取出data[s],s--会删除栈顶的元素
    }
}

The chain storage structure and implementation of the stack

  1. The singly linked list has a head pointer, and the top pointer of the stack is also necessary, so put the top of the stack at the head of the singly linked list (head node -> stack top)
  2. The chain stack basically does not exist when the stack is full; for an empty stack, the linked list originally defined the head pointer to point to empty, then the empty of the chain stack is top = NULL
typedef struct StackNode
{
    
    
    ElemType data;
    struct StackNode *next;
}StackNode, *LinkStackPtr;

typedef struct LinkStack
{
    
    
    LinkStackPtr top;
    int count
}LinkStack;
/*
进栈操作:单链表有头指针,而栈顶指针也是必须的,因此把栈顶放在单链表的头部(头结点->栈顶):相当于头插法;插入新元素e为新的栈顶元素
 */
Status Push(LinkStack *S,SElemType e)
{
    
    
    LinkStackPtr s=(LinkStackPtr) malloc(sizeof(StackNode)); /*声明新结点*/
    s->data = e;
    s->next = S->top;  /*把当前的栈顶元素赋值给新结点的直接后继*/
    S->top = s;  /*将新的结点s赋值给栈顶指针*/
    S->count++;
    return OK;
}
/*出栈操作:用p存储被删除的栈顶结点,将栈顶指针下移一位,最后释放p*/
#include <stdbool.h>
bool StackEmpty(LinkStack S)
{
    
    
    if(S.top ==NULL) /*如果是空栈,则top为*/
        return TRUE;
}
Status Pop(LinkStack *S,SElemType *e)
{
    
    
    LinkStackPtr p;
    if (StackEmpty(*S))
        return ERROR;
    *e = S->top->data;
    p = S->top;
    S->top = S->top->next;
    free(p);
    S->count--;
    return OK;
}

Stack application

  1. Recursion, a function that directly calls itself or indirectly calls itself through a series of call statements is called a recursive function. Pay attention to the definition of the conditional command for exiting when the call is not satisfied
    . a. In the previous stage, for each level of recursion, the function The local variables, parameter values ​​and return addresses of the will be pushed onto the stack.
    b. In the retreat phase, the local variables, parameter values, and return address at the top of the stack are popped up, used to return to the rest of the code executed in the call hierarchy, and restore the call state
  2. Four regular expressions are evaluated
    a. The expressions with parentheses go from left to right, the stack is empty to have elements, and finally becomes an empty stack after all matches are successful
    . b. Postfix expressions and infix expressions (standard four arithmetic expressions) )

queue

When the maximum length of the queue can be determined, it is recommended to use a circular queue; when the length of the queue cannot be estimated, use a chain queue

  1. Linear table that only allows insert operation at one end and delete operation at the other end -> first in first out FIFO
  2. The queue is obtained based on the sequential storage structure of the linear table. When leaving the queue, all must be moved. The elements of the queue must be stored in the first n units of the array, and the dequeue performance will be greatly increased.
  3. In order to avoid when there is only one element, the head and tail of the team overlap and cause trouble, use two pointers front (point to the head element) and rear (point to the tail element)
    3.1. Question 1: front (point to the head element), rear (Pointing to the element at the end of the queue), but it will lead to the situation where the
    end of the queue has no position but the head of the queue has a position -> Use the sequential storage structure of the queue end to end, which is recorded as a circular queue
    . front == rear, but the condition is also met when the queue is full
    -> Method 1: Set the flag variable, when flag =0, the queue is empty; when flag = 1, the queue is full
    -> Method 2: When the queue is full, keep an element Space
    a. Queue full condition: (rear+1)%QueueSize == front (rear may be on the right side of the front or on the left side of the front)
    b. Queue length: (rear-front+QueueSize)

Sequential storage structure of circular queue

typedef int QElemType; //视情况而定
typedef struct
{
    
    
    QElemType data[MAXSIZE];
    int front; /*头指针*/
    int rear; /*尾指针,若队列不空,指向队列元素的下一个位置*/
}SqQueue;

/*初始化一个空队列*/
Status InitQueue(SqQueue *Q)
{
    
    
    Q->front= 0;
    Q->rear=0;
    return OK;
}
/*返回Q的元素个数,也就是队列的当前长度*/
int QueueLength(SqQueue Q)
{
    
    
    return (Q.rear - Q.front+MAXSIZE)%MAXSIZE;
}
/*循环队列的入队列操作代码*/
Status EnQueue(SqQueue *Q,QElemType e) {
    
    
    if ((Q->rear + 1) % MAXSIZE == Q->front) /*队列满的判断*/
        return ERROR;
    Q->data[Q->rear] = e;  //将元素e赋值给队尾
    Q->rear = (Q->rear + 1) % MAXSIZE; //rear指针向后移一个位置,在末尾则转到数组头部
}

/*循环队列的出队列操作代码*/
Status DeQueue(SqQueue *Q,QElemType *e)
{
    
    
    if (Q->front == Q->rear)
        return ERROR;
    *e= Q->data[Q->front]; //将队头元素赋值给e
    Q->front=(Q->front+1)%MAXSIZE; //front指针向后移一位置,若到最后转到数组头部
}

Chain queue

Single-linked list of linear table, end-in and end-out, chain storage structure and realization of queue

typedef int QElemType;
typedef struct QNode
{
    
    
    QElemType data;
    struct QNode *next;
}QNode,*QueuePtr;

typedef struct  //队列的链表结构
{
    
    
    QueuePtr front,rear; //对头、队尾指针
}LinkQueue;

/*插入元素e为Q的新的队尾元素*/
#include <math.h>
Status EnQueue(LinkQueue *Q,QElemType e)
{
    
    
    QueuePtr  s = (QueuePtr) malloc(sizeof(QNode));
    if (!s)  //存储分配失败
        exit(OVERFLOW);
    s->data=e;
    s->next=NULL;
    Q->rear->next=s; //把拥有yuansue新结点s赋值为原队尾结点的后继
    Q->rear=s; //把当前的s设置为队尾结点,rear指向s
    return OK;
}
Status DeQueue(LinkQueue *Q,QElemType *e)
{
    
    
    QueuePtr p;
    if (Q->front == Q->rear)
        return ERROR;
    p= Q->front->next; //将要删除的队头结点暂存给p
    *e = p->data; // 将要删除的队头结点的值赋值给*e
    Q->front->next = p->next; //将原队头结点后继赋值给头结点后继
    if (Q->rear == p)
        Q->rear = Q->front; //若队头是队尾,则删除后将rear指向头结点(只有头结点和一个元素)
    free(p);
    return OK;
}

Guess you like

Origin blog.csdn.net/weixin_43464554/article/details/113264820