zoukankan      html  css  js  c++  java
  • 栈与队列

    定义:

    栈(Stack),是运算受限的线性表,插入和取出操作都只能在表头进行,也称之为后进先出(LIFO)线性表;

    案例:

    有名为stk的栈,按顺序插入:1,2,3三个元素,插入完成后取出全部,顺序为:3,2,1;

    栈的实现:

    既然是线性表,则可以通过顺序结构和链接结构来实现,通过顺序结构实现的栈称为顺序栈,通过链接结构实现的栈称为链栈;

    常用操作:
    • 初始化
    • 入栈
    • 出栈
    • 取栈顶元素
    • 空栈判断
    使用场景:

    程序中函数(方法)的执行通常都是借助栈来完成的,当要执行一个函数时,会将函数代码压入栈中,执行完毕则出栈,执行过程中若调用了其他函数,则被调函数同样会入栈,所以程序中的函数嵌套调用时,也是遵循后进先出;

    顺序实现

    顺序栈数据结构:

    c语言实现:
    #include <stdio.h>
    
    //栈的顺序实现
    //定义数据结构
    const int SIZE = 5;
    typedef struct{
        int data[SIZE];
        int top;
    }seqStk,*SEQStack;
    
    SEQStack initalStack(){
        SEQStack stack = malloc(sizeof(seqStk));
        stack->top = -1;
        return stack;
    }
    
    int isEmpty(SEQStack stack){
        if(stack->top == -1){
            return 1;
        }
        return 0;
    }
    
    int getTop(SEQStack stack){
        if (isEmpty(stack)) {
            printf("err:stack is empty!
    ");
            return NULL;
        }else{
            return stack->data[stack->top];
        }
    }
    
    int pop(SEQStack stack){
        //先进后出,出栈是判断是否空
         if (isEmpty(stack)) {
               printf("err:stack is empty!
    ");
               return NULL;
         }else{
             int temp = getTop(stack);
             stack->top--;
             return temp;
         }
    }
    
    
    void push(SEQStack stack,int data){
        if (stack->top == SIZE-1) {
            printf("err:stack already full!
    ");
        }else{
            stack->top++;
            stack->data[stack->top] = data;
        }
    }
    
    
    int main(int argc, const char * argv[]) {
        SEQStack stack = initalStack();
        push(stack,100);
        push(stack,200);
        push(stack,300);
        push(stack,400);
        push(stack,500);
        push(stack,600);
        printf("geted:%d
    ",pop(stack));
        printf("geted:%d
    ",getTop(stack));
        printf("geted:%d
    ",pop(stack));
        printf("geted:%d
    ",pop(stack));
        printf("geted:%d
    ",pop(stack));
        printf("geted:%d
    ",pop(stack));
        printf("Hello, World!
    ");
        return 0;
    }
    
    双栈

    顺序实现的弊端就在于,无法预估数据长度,会造成空间浪费,为了避免这个问题,我们可以让两个栈共享同一个顺序存储空间,起始地址和结束地址分别作为两个栈的栈底;

    • 数据结构及相关操作:

    链接实现

    数据结构:

    c语言实现:
    #include <stdio.h>
    
    //结构定义
    typedef struct node{
        int data;
        struct node *next;
    }Node,*LinkStk;
    
    LinkStk initialStack(){
        LinkStk stack = malloc(sizeof(Node));
        stack->next = NULL;
        return stack;
    }
    
    int isEmpty(LinkStk stack){
        if (stack->next == NULL) {
            return 1;
        }
        return 0;
    }
    
    void push(LinkStk stack,int data){
        Node *p = malloc(sizeof(Node));
        p->next = stack->next;
        p->data = data;
        stack->next = p;
    }
    
    Node *getTop(LinkStk stack){
        return stack->next;
    }
    
    void *pop(LinkStk stack){
        if (isEmpty(stack)) {
            printf("error:stack is empty!
    ");
            return NULL;
        }
        Node *temp = stack->next;
        stack->next = temp->next;
        free(temp);
    }
    
    int main(int argc, const char * argv[]) {
        LinkStk stack = initialStack();
        push(stack, 100);
        push(stack, 200);
        push(stack, 300);
    
        pop(stack);
        pop(stack);
        pop(stack);
    
        Node *a = getTop(stack);
        if (a != NULL){
            printf("%d
    ",a->data);
        }
    
        push(stack, 900);
        Node *w = getTop(stack);
        printf("%d
    ",w->data);
        printf("Hello, World!
    ");
        return 0;
    }
    

    案例中所有操作算法时间复杂度均为O(1);

    队列

    定义:

    队列(Queue),同栈相同,也是运算受限的线性表,其插入只能在表未进行,而删除只能在表头进行,称之为先进先出(FIFO)线性表;

    案例:

    有名为stk的栈,按顺序插入:1,2,3三个元素,插入完成后取出全部,顺序为:1,2,3;

    队列的实现:

    既然是线性表,同样也可以通过顺序结构和链接结构来实现;

    常用操作:
    • 初始化
    • 入队列
    • 出队列
    • 取队列首元素
    • 空队列判断
    使用场景:

    队列的核心就在于,先来先得,先进队列的一定先出,这非常适合用在需要保证处理顺序的业务上,例如秒杀活动;

    顺序实现

    队列中的元素是具有顺序的所以可通过顺序结构实现,常见的方式就是通过数组,但是数组的问题是无法准确预估元素大小

    此外,当有元素从队列中出去时,队列则可以存如储新的元素,但是心存储的元素应该放在那里却成了一个问题,

    实现原理简述:

    c语言实现:
    #include <stdio.h>
    
    const int max_size = 5;
    
    //数据结构定义
    typedef struct LQueue{
        int data[max_size];
        int front;
        int rear;
    }LQueue,*Queue;
    
    //初始化
    LQueue *initial(){
        LQueue *queue = malloc(sizeof(LQueue));
        queue->front = 0;
        queue->rear = 0;
        return queue;
    }
    
    //入队列
    void put(LQueue *queue,int data){
        if ((queue->rear+1)%max_size == queue->front){
            printf("error:队列已满
    ");
            exit(-1);
        } else{
            queue->rear = (queue->rear+1)%max_size;
            queue->data[queue->rear] = data;
        }
    }
    
    //判空
    int isEmpty(LQueue *queue){
        return queue->rear == queue->front;
    }
    
    //出队列
    int get(LQueue *queue){
        if (isEmpty(queue)){
            printf("error:队列为空");
            exit(-1);
        }else{
            queue->front = (queue->front+1)%max_size;
            return queue->data[queue->front];
        }
    }
    
    //测试
    int main(int argc, const char * argv[]) {
        Queue  queue = initial();
        put(queue,1);
        put(queue,2);
        put(queue,3);
        put(queue,4);
        printf("%d
    ",get(queue));
        printf("%d
    ",get(queue));
        put(queue,5);
        put(queue,6);
        printf("%d
    ",get(queue));
        printf("%d
    ",get(queue));
        printf("%d
    ",get(queue));
        printf("%d
    ",get(queue));
        put(queue,7);
        printf("%d
    ",get(queue));
        printf("Hello, World!
    ");
        return 0;
    }
    ```![](https://img2020.cnblogs.com/blog/1440878/202004/1440878-20200423165956826-613812768.png)
    ![](https://img2020.cnblogs.com/blog/1440878/202004/1440878-20200423165959774-971029359.png)
  • 相关阅读:
    剑指offer——包含min函数的栈
    剑指offer——顺时针打印矩阵
    剑指offer——二叉树的镜像
    剑指offer——树的子结构
    爬虫的单线程+多任务异步协程:asyncio 3.6
    爬虫中的模拟登陆,IP代理,线程池
    爬虫-数据解析
    爬虫基础
    Markdown语法
    Git
  • 原文地址:https://www.cnblogs.com/yangyuanhu/p/12745053.html
Copyright © 2011-2022 走看看