• 栈和队列


    栈就像一个弹匣,一个个往里放子弹,你最后放进去的子弹,最先打出来,如果不打出后面的子弹,那你先放的子弹就打不出来。

    如图所示:

     后来者居上,后存入的数据放在栈顶,先存入的数据放于栈底,只有把栈顶部的数据拿出来,才能拿到下面 先存入的数据。

    我们用链表写一个链栈,因为基本都是前面单向链表的知识,所以这里不单独列出每个函数的功能了。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct node
    {
        int data;
        struct node *next;
    }stack;
    
    /***************函数声明*****************/
    stack *BuildStack();
    int PushStack(stack *p_stack,int data);
    int ReadStackTop(stack *p_stack);
    void ReadStackData(stack *p_stack);
    int PopStack(stack *p_stack);
    void FreeStatic(stack *p_stack);
    stack *CreateStack(stack *p_stack);
    int EmptyStack(stack *p_stack);
    
    /*****************************************
    *函数作用:创建一个节点
    *输入参数:节点数据
    *返 回 值:头节点
    *备    注:
    *****************************************/
    stack *BuildStack(int data)
    {
        stack *p_creat = NULL;
        p_creat = (stack *)malloc(sizeof(stack));
        if (p_creat == NULL)
        {
            printf("ERROR:BuildStack创建节点失败
    ");
            exit(0);    
        }
        memset(p_creat,0,sizeof(stack));
        p_creat->data = data;
        p_creat->next = NULL;
        return p_creat;
    }
    
    /*****************************************
    *函数作用:创建一个栈
    *输入参数:栈
              第一个元素值
    *返 回 值:栈内第一个(最后一个元素)
    *备    注:
    *****************************************/
    stack *CreateStack(stack *p_stack)
    {
        stack *p_tmp = BuildStack(0);
        p_stack = p_tmp;
        p_tmp->next = NULL;
        return p_tmp;
    }
    
    /*****************************************
    *函数作用:压栈(入栈)
    *输入参数:栈指针,加入的数据
    *返 回 值:成功1 失败0
    *备    注:在栈顶存入数据(链表尾)
    *****************************************/
    int PushStack(stack *p_stack,int data)
    {
        stack *p_creat = BuildStack(data);
        stack *p_tmp = p_stack;
        if (p_stack == NULL)
        {
            printf("ERROR:PushStack该栈未初始化
    ");
            return 1;
        }
        else
        {
            while(p_tmp->next != NULL)
            {
                p_tmp = p_tmp->next;
            }
            p_tmp->next = p_creat;
            if (data == ReadStackTop(p_stack))
            {
                printf("存入栈顶成功
    ");
                return 1;
            }
            else
            {
                printf("ERROR:PushStack存入栈顶失败
    ");
                return 0;
            }
        }
    }
    
    
    /*****************************************
    *函数作用:读栈顶元素值
    *输入参数:栈
    *返 回 值:栈顶数据     
    *备    注:
    *****************************************/
    int ReadStackTop(stack *p_stack)
    {
        stack *p_tmp = p_stack;
        if (EmptyStack(p_stack) == 0)
        {
            printf("ERROR:ReadStackTop 空栈 读取栈顶元素失败
    ");        
            return;
        }
        else
        {
            while(p_tmp->next != NULL)
            {
                p_tmp = p_tmp->next;
            }
            printf("栈顶的值为%d
    ",p_tmp->data);
            return p_tmp->data;
        }
    }
    
    /*****************************************
    *函数作用:读栈里所有值
    *输入参数:栈
    *返 回 值:     
    *备    注:
    *****************************************/
    void ReadStackData(stack *p_stack)
    {
        stack *p_tmp = p_stack->next;
        int i = 0;
        printf("------------------------
    ");
        while(p_tmp != NULL)
        {
            printf("%d	",p_tmp->data);
            p_tmp = p_tmp->next;
            i++;
        }
    
        printf("
    ------------------------
    ");
    }
    
    /*****************************************
    *函数作用:出栈
    *输入参数:栈
    *返 回 值:成功1 失败0     
    *备    注:
    *****************************************/
    int PopStack(stack *p_stack)
    {
        stack *p_tmp = p_stack,*p_free = p_stack;
        if (EmptyStack(p_stack) == 0)
        {
            printf("ERROR:PopStack 空栈 出栈失败
    ");
            return 0;
        }
        else
        {
            while(p_free->next != NULL)
            {
                p_tmp = p_free;
                p_free = p_free->next;
            }
            p_tmp->next = NULL;
            free(p_free);
            return 1;
        }
    }
    
    /*****************************************
    *函数作用:清空栈
    *输入参数:栈
    *返 回 值:     
    *备    注:
    *****************************************/
    void FreeStatic(stack *p_stack)
    {
        //p_tmp从头节点开始一路往后指,遇到不为空(需要free)的节点便将该节点交给p_free释放
        stack *p_tmp = p_tmp,*p_free = NULL;
        while(p_tmp != NULL)
        {
            p_free = p_tmp;
            p_tmp = p_tmp->next;
            free(p_free);
        }
    }
    
    /*****************************************
    *函数作用:判断栈是否为空
    *输入参数:栈
    *返 回 值:0为空 1非空     
    *备    注:
    *****************************************/
    int EmptyStack(stack *p_stack)
    {
        stack *p_tmp = p_stack;
        if (p_stack->next == NULL)
        {
            return 0;
        }
        return 1;
    }
    
    
    int main(int argc, char const *argv[])
    {
        //创建一个栈
        stack *p_stack = CreateStack(p_stack);
        //依次从栈顶加入数个数据
        PushStack(p_stack,5);
        ReadStackData(p_stack);
        PushStack(p_stack,10);
        ReadStackData(p_stack);
        PushStack(p_stack,15);
        ReadStackData(p_stack);
        //出栈
        PopStack(p_stack);
        ReadStackData(p_stack);
        //读栈顶元素
        ReadStackTop(p_stack);
        //一个一个全扔出去
        PopStack(p_stack);
        PopStack(p_stack);
        ReadStackData(p_stack);
        //空栈时出栈
        PopStack(p_stack);
    
        FreeStatic(p_stack);
        return 0;
    }

    运行结果如下,充分说明我们的代码的正确:

    队列

    队列就类似于我们排队买票。

    先来排队的人就先买票,后来的人在后面排队,只有前面的买完票了,离开之后,后面的人才可以买到票。

     

    下面我们用一个数组当做队列,两个指针分别指向队列的头和队列尾,将他们封进一个结构体里

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    typedef struct Queue
    {
        int a[10];
        int head;    //指向数组头
        int tail;    //指向数组尾
    }queue;
    
    /************函数声明************/
    queue *QueueInit(void);
    int InQueue(queue *p_queue,int data);
    int OutQueue(queue *p_queue);
    void PrintfQueue(queue *p_queue);
    
    /********************
    *函数功能:队列初始化
    *输入参数:
    *返    回:新建队列名
    *********************/
    queue *QueueInit(void)
    {
        queue *p_creat = NULL;
        p_creat = (queue *)malloc(sizeof(queue));
        if (p_creat == NULL)
        {
            printf("ERROR:QueueInit队列初始化失败
    ");
            exit(0);    
        }
        p_creat->head = 0;
        p_creat->tail = 0;
        return p_creat;
    }
    
    /********************
    *函数功能:在队里末尾插入新数据
    *输入参数:
            queue 队列名
            data 新加入数据
    *返    回:
    *********************/
    int InQueue(queue *p_queue,int data)
    {
        p_queue->a[p_queue->tail] = data;
        p_queue->tail++;    
        return data;
    }
    
    /********************
    *函数功能:队列头删除一个数据
    *输入参数:
            queue 队列名
    *返    回:
    *********************/
    int OutQueue(queue *p_queue)
    {
        p_queue->a[p_queue->head] = 0;
        p_queue->head++;
        return 0;
    }
    
    /********************
    *函数功能:打印队列全部数据
    *输入参数:
            queue 队列名
    *返    回:
    *********************/
    void PrintfQueue(queue *p_queue)
    {
        int i = 0;
        int tmp = p_queue->head;
        printf("--------------------
    ");
        for (i = 0; i < 20; ++i)
        {
            if (tmp+i != p_queue->tail)
            {
                printf("%d	",p_queue->a[tmp+i]);
            }
            else{break;}
        }
        printf("
    --------------------
    ");
    }
    
    
    
    int main()
    {
        queue *p_queue = QueueInit();
        InQueue(p_queue,1);
        PrintfQueue(p_queue);
        InQueue(p_queue,2);
        PrintfQueue(p_queue);
        InQueue(p_queue,3);
        PrintfQueue(p_queue);
    
        OutQueue(p_queue);
        PrintfQueue(p_queue);
        OutQueue(p_queue);
        PrintfQueue(p_queue);
        
        return 0;
    }

    运行结果如下:

    看上去十分美好,就是我想要的结果,但是如果我打印整个数组,就会发现问题

        //打印整个数组
        for ( i = 0; i < 10; ++i)
        {
            printf("%d	", p_queue->a[i]);
        }

     对,数组前面OutQueue的两个元素是没了,但是这个坑还留着,浪费了空间

    而且我定义结构体时也只给了数组10个坑,这10个坑用完了就没了

    针对这种情况,我们对刚才的队列做如下改动:

    首先define定义一个CUBAGE 替代数组容量

    #define CUBAGE 10    //队列数组容量

    当尾指针指向数组的末尾时,如果前面还有空间,则尾指针指向数组首地址,让前面已经走掉的坑位重复利用

    在调试到这里时,我遇到一个问题:

    我采取判断队列是否满员的方式是    p_queue->tail == p_queue->head

    这就有了麻烦,就是在初始化队列的时候头尾指针确实是相等的,所以如果加入了这个条件,必须想办法让他跳过初始化之后第一次给队列赋值的判断,所以这里我放了一个标志位flg,初始化的时候 flg = 1,第一次赋值过后flg变为0,所以在判断满员的同时判断flg,若 flg = 0 则已经完成了第一次的赋值 这个时候再用头尾指针相等就可以判断是否满员了。

    所以插入数据函数更改为:

    /********************
    *函数功能:在队里末尾插入新数据
    *输入参数:
            queue 队列名
            data 新加入数据
    *返    回:data 成功 0失败
    *********************/
    int InQueue(queue *p_queue,int data)
    {
        //尾指针走到最后 然后返回队列头
        if(p_queue->tail == CUBAGE)
        {
            p_queue->tail = 0;
        }
        //尾指针再一次和头指针相等时 判断为满
        if (p_queue->tail == p_queue->head && flg == 0)
        {
            printf("ERROR:InQueue队列已满加入失败
    ");
            return 0;
        }
        p_queue->a[p_queue->tail] = data;
        p_queue->tail++;    
        flg = 0;
        return data;
    }

    全部代码如下:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define CUBAGE 5    //队列数组容量
    
    int flg;
    
    typedef struct Queue
    {
        int a[CUBAGE];
        int head;    //指向数组头
        int tail;    //指向数组尾
    }queue;
    
    /************函数声明************/
    queue *QueueInit(void);
    int InQueue(queue *p_queue,int data);
    int OutQueue(queue *p_queue);
    void PrintfQueue(queue *p_queue);
    
    /********************
    *函数功能:队列初始化
    *输入参数:
    *返    回:新建队列名
    *********************/
    queue *QueueInit(void)
    {
        queue *p_creat = NULL;
        p_creat = (queue *)malloc(sizeof(queue));
        if (p_creat == NULL)
        {
            printf("ERROR:QueueInit队列初始化失败
    ");
            exit(0);    
        }
        memset(p_creat,0,sizeof(p_creat));
        p_creat->head = 0;
        p_creat->tail = 0;
        flg = 1;
        return p_creat;
    }
    
    /********************
    *函数功能:在队里末尾插入新数据
    *输入参数:
            queue 队列名
            data 新加入数据
    *返    回:data 成功 0失败
    *********************/
    int InQueue(queue *p_queue,int data)
    {
        //尾指针走到最后 然后返回队列头
        if(p_queue->tail == CUBAGE)
        {
            p_queue->tail = 0;
        }
        //尾指针再一次和头指针相等时 判断为满
        if (p_queue->tail == p_queue->head && flg == 0)
        {
            printf("ERROR:InQueue队列已满加入失败
    ");
            return 0;
        }
        p_queue->a[p_queue->tail] = data;
        p_queue->tail++;    
        flg = 0;
        return data;
    }
    
    /********************
    *函数功能:队列头删除一个数据
    *输入参数:
            queue 队列名
    *返    回:
    *********************/
    int OutQueue(queue *p_queue)
    {
        p_queue->a[p_queue->head] = 0;
        p_queue->head++;
        if (p_queue->head == CUBAGE)
        {
            p_queue->head = 0;
        }
        return 0;
    }
    
    /********************
    *函数功能:打印队列全部数据
    *输入参数:
            queue 队列名
    *返    回:
    *********************/
    void PrintfQueue(queue *p_queue)
    {
        int i = 0;
        printf("--------------------
    ");
        for (i = 0; i < CUBAGE; ++i)
        {
            printf("%d	",p_queue->a[i]);            
        }
        printf("
    --------------------
    ");
    }
    
    
    int main()
    {
        queue *p_queue = QueueInit();
        InQueue(p_queue,1);
        PrintfQueue(p_queue);
        InQueue(p_queue,2);
        PrintfQueue(p_queue);
        InQueue(p_queue,3);
        PrintfQueue(p_queue);
        InQueue(p_queue,4);
        PrintfQueue(p_queue);
        InQueue(p_queue,5);
        PrintfQueue(p_queue);
    
        InQueue(p_queue,6);
        PrintfQueue(p_queue);
        
        return 0;
    }

    测试暂时没有什么问题,接下来我们看一下熟悉的链表操作。。。

    熟悉的malloc熟悉的memset熟悉的末尾增加熟悉的释放。。。

    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    typedef struct Node
    {
        int data;
        struct Node *next;
    }node;
    
    typedef struct Queue
    {
        int size_queue;
        struct Queue *head;
        struct Queue *tail;
    }queue;
    
    /*******函数初始化********/
    node *CreatNode(int data);
    queue *CreatQueue(void);
    int InsertQueueData(queue *p_queue,int data);
    void PrintfQueue(queue *p_queue);
    void DeleteQueueData(queue *p_queue);
    void FreeQueue(queue *p_queue);
    
    /********************
    *函数功能:新建节点
    *输入参数:新数据
    *返回值  :新节点指针
    *********************/
    node *CreatNode(int data)
    {
        node *p_creat = NULL;
        p_creat = (node *)malloc(sizeof(node));
        if (p_creat == NULL)
        {
            printf("ERROR:CreatNode 新建节点失败
    ");
            exit(0);
        }
        memset(p_creat,0,sizeof(node));
        p_creat->data = data;
        p_creat->next = NULL;
        return p_creat;
    }
    
    /********************
    *函数功能:新建队列
    *输入参数:
    *返回值  :新队列指针
    *********************/
    queue *CreatQueue(void)
    {
        queue *p_creat = NULL;
        p_creat = (queue *)malloc(sizeof(queue));
        if (p_creat == NULL)
        {
            printf("ERROR:CreatQueue 新建队列失败
    ");
            exit(0);
        }
        memset(p_creat,0,sizeof(queue));
        p_creat->size_queue = 0;
        p_creat->head = NULL;
        p_creat->tail = NULL;
        return p_creat;
    }
    
    /********************
    *函数功能:在队列尾加入新数据
    *输入参数:
                p_queue    队列
                data    要加入的数据
    *返回值  :
    *********************/
    int InsertQueueData(queue *p_queue,int data)
    {
        node *p_tmp = p_queue->tail;
        node *p_creat = CreatNode(data);
        if (p_tmp != NULL)
        {
            p_tmp->next = p_creat;
        }
        p_queue->tail = p_creat;
        p_queue->size_queue++;
    
        if (p_queue->head == NULL)
        {
            p_queue->head = p_creat;
        }
        return 0;
    }
    
    
    /********************
    *函数功能:打印整个队列
    *输入参数:队列名
    *返回值  :
    *********************/
    void PrintfQueue(queue *p_queue)
    {
        node *tmp = p_queue->head;
        printf("队列共有%d元素	", p_queue->size_queue);
        while(tmp != NULL)
        {
            printf("%d	",tmp->data);
            tmp = tmp->next;
        }
        printf("
    -----------------
    ");
    }
    
    
    /********************
    *函数功能:删除头数据
    *输入参数:队列名
    *返回值  :
    *********************/
    void DeleteQueueData(queue *p_queue)
    {
        node *tmp = p_queue->head;
        if (p_queue->head == NULL)
        {
            printf("ERROR:DeleteQueueData 队列为空 删除失败
    ");
        }
        else
        {
            if (tmp->next != NULL)
            {
                p_queue->head = tmp->next;
                p_queue->size_queue--;
                free(tmp);
            }
            else
            {
                free(tmp);
                p_queue->head = NULL;
                p_queue->tail = NULL;
                p_queue->size_queue = 0;
            }
        }
        return;
    }
    
    /********************
    *函数功能:释放队列 数据全部清除
    *输入参数:队列名
    *返回值  :
    *********************/
    void FreeQueue(queue *p_queue)
    {
        int i ;
        for ( i = 0; i < p_queue->size_queue; ++i)
        {
            DeleteQueueData(p_queue);
        }
        free(p_queue);
        return;
    }
    
    
    
    
    int main(int argc, char const *argv[])
    {
        queue *p_queue = CreatQueue();
    
        InsertQueueData(p_queue,1);
        PrintfQueue(p_queue);
        InsertQueueData(p_queue,2);
        PrintfQueue(p_queue);
        InsertQueueData(p_queue,3);
        PrintfQueue(p_queue);
        DeleteQueueData(p_queue);
        PrintfQueue(p_queue);
        DeleteQueueData(p_queue);
        PrintfQueue(p_queue);
        InsertQueueData(p_queue,4);
        PrintfQueue(p_queue);
        DeleteQueueData(p_queue);
        PrintfQueue(p_queue);
        DeleteQueueData(p_queue);
        PrintfQueue(p_queue);
        DeleteQueueData(p_queue);
        PrintfQueue(p_queue);
        InsertQueueData(p_queue,1);
        PrintfQueue(p_queue);
        InsertQueueData(p_queue,2);
        PrintfQueue(p_queue);
        InsertQueueData(p_queue,3);
        PrintfQueue(p_queue);
    
        FreeQueue(p_queue);
        return 0;
    }

    运行结果如下:

  • 相关阅读:
    牛客练习赛19 D-托米去购物
    牛客练习赛19 托米的简单表示法
    Codeforces Round #492 (Div. 2) [Thanks, uDebug!]
    Codeforces Round #393 (Div. 2) (8VC Venture Cup 2017
    Codeforces Round #393 (Div. 2) (8VC Venture Cup 2017
    Codeforces Round #491 (Div. 2) E
    I00018 生成全1数
    I00017 生成9开头的按位递减数
    I00017 生成9开头的按位递减数
    HDU1042 n!
  • 原文地址:https://www.cnblogs.com/qifeng1024/p/12512765.html
Copyright © 2020-2023  润新知