zoukankan      html  css  js  c++  java
  • 顺序栈的总结

    基本数据结构之-顺序栈

    栈是一种先进后出的数据结构,我们可以使用一个数组来模拟栈的这种结构,将数组的尾部当做栈的栈顶似乎是一个不错的选择(插入和移除元素是不涉及到数据的移动),也可以很好的控制数组的长度,和数据的进栈和出栈!

    首先先解析一下顺序栈的数据结构

    1 需要一个数据域来存储数据 考虑到可能存储自定义的数据类型,所以我们选择存储每个数据的开始的地址 (void **stack)

    2 需要一个值来记录当前的数据域的长度 (size)

    3 需要一个值来记录当前的容器的长度

    typedef struct _QUEUESTACK

    {

        // 栈的数据

        void **Stack;

     

        // 栈的数据长度

        int Size;

     

        // 栈的容量

        int Capacity;

    }QueueStack;

    接下来是栈的初始化

    需要传入一个容量的参数,主要是测试的时候,我可以把长度设置小一点,哈哈!

    // 初始化栈

    int Init_QueueStack(void **queuestack, int capacity)

    {

        if (queuestack == NULL)

        {

            exit(-1);

        }

        // 定义一个栈结构体的指针

        QueueStack *stack = (QueueStack *)malloc(sizeof(QueueStack));

     

        // 判断开辟内存是否成功

        if (stack == NULL)

        {

            exit(-2);

        }

     

        // 为stack 开辟一段堆内存

        stack->Stack = (void **)malloc(sizeof(void *)*capacity);

     

        // 判断开辟内存是否成功

        if (stack->Stack == NULL)

        {

            exit(-2);

        }

     

        // 写入相关的变化

        stack->Capacity = capacity;

        stack->Size = 0;

     

        // 将开辟出来的空间置零

        memset(stack->Stack, 0, sizeof(void *)*stack->Capacity);

     

        *queuestack = stack;

        return 0;

    }

    入栈,当数据的长度等于容量时需要动态的开辟新的空间

    //入栈

    int Push_QueueStack(void *queuestack, void *data)

    {

        // 对传入的参数做判断

        if (queuestack == NULL)

        {

            return -1;

        }

        if (data == NULL)

        {

            return -2;

        }

     

        // 将指针转化为我们可以操作的类型

        QueueStack *stack = (QueueStack *)queuestack;

        if (stack->Size == stack->Capacity)

        {

            // 当数据域的长度不够时,进行动态开辟

            void ** newStack = (void **)malloc(stack->Capacity * 2);

            if (newStack == NULL)

            {

                return -3;

            }

            // 将开辟的空间全部置零

            memset(newStack, 0, sizeof(void *)* stack->Capacity * 2);

     

            // 将原来的数据拷贝到新的栈

            memcpy(newStack, stack->Stack, sizeof(void *)*stack->Capacity);

     

            // 释放原来栈的空间

            free(stack->Stack);

     

            // 将栈的数据域指向新的位置

            stack->Stack = newStack;

            stack->Capacity *= 2;

        }

     

        // 将数据加入到栈的数据域中

        stack->Stack[stack->Size] = data;

        ++stack->Size;

     

        return 0;

    }

    //出栈 当数据域的长度为0 时,就不能正常的出栈了

    int Pop_QueueStack(void *queuestack)

    {

        if (queuestack == NULL)

        {

            return -1;

        }

     

        // 将指针转化为我们可以操作的类型

        QueueStack *stack = (QueueStack *)queuestack;

     

        // 数据域没数据没法出栈

        if (stack->Size == 0)

        {

            return -2;

        }

        else

        {

            // 先将长度减一

            --stack->Size;

     

            // 将最后一个元素的位置空

            stack->Stack[stack->Size] = NULL;

        }

        return 0;

     

    }

    获取栈顶的元素 当栈的数据域的长度为0 时 栈顶元素为空

    void * Top_QueueStack(void *queuestack)

    {

        if (queuestack == NULL)

        {

            return NULL;

        }

     

        // 将指针转化为我们可以操作的类型

        QueueStack *stack = (QueueStack *)queuestack;

     

        // 数据域没数据没法出栈

        if (stack->Size == 0)

        {

            return NULL;

        }

        else

        {

            return stack->Stack[stack->Size - 1];

        }

    }

    销毁栈,一定要记住不要释放数据域,因为存储的是地址,我们并不知道需要释放的是开辟的堆内存还是栈内存,也不知道每个地址下的数据域的长度,所以还是交给使用者去释放吧

    int Destory_QueueStack(void *queuestack)

    {

        if (queuestack == NULL)

        {

            return -1;

        }

     

        // 将指针转化为我们可以操作的类型

        QueueStack *stack = (QueueStack *)queuestack;

     

        if (stack->Stack != NULL)

        {

            // 不知道这段内存的位置(栈内存还是堆内存) 里面存储的是地址 由使用者自己管理

            //free(stack->Stack);

     

            stack->Stack = NULL;

            stack->Size = 0;

            stack->Capacity = 0;

        }

        free(stack);

     

        return 0;

    }

    // 栈的长度

    int Size__QueueStack(void *queuestack)

    {

        if (queuestack == NULL)

        {

            return -1;

        }

     

        // 将指针转化为我们可以操作的类型

        QueueStack *stack = (QueueStack *)queuestack;

     

        return stack->Size;

     

    }

    如果想把开辟的数组的其实位置看做栈顶的话,在每次入队的时候记得把所有已经存在的数据向后移动一个位置,同时出栈的时候,需要向前移动一个位置。

  • 相关阅读:
    meta_value与meta_value_num的区别(排序)
    B:Wordpress不同分类调用不同的模板
    C:Wordpress自定义文章类型(图视频)
    D:Wordpress_AFC插件常用代码
    A:手把手教Wordpress仿站(基础)
    JS之Form表单相关操作
    PHP常用代码汇总
    mysql_fetch_array,mysql_fetch_row,mysql_fetch_assoc区别
    数据库、数据库表的创建与删除
    Android实现智能提示的文本输入框AutoCompleteTextView
  • 原文地址:https://www.cnblogs.com/bkcarlos/p/5926684.html
Copyright © 2011-2022 走看看