zoukankan      html  css  js  c++  java
  • 练习系列 3、设计包含min函数的栈,push、pop、min的时间复杂度都为O(1),仿照APR_RING采用宏实现

    /*!
    \author LiuBao
    \date 2011/3/4
    \brief 设计包含min函数的栈
    定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。
    要求函数min、push以及pop的时间复杂度都是O(1)。
    这里给出整个栈的宏实现,使用链式栈,仿照APR_RING设计宏函数。
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>     /* 比较函数中使用assert */
     
    /*!
    在任意结构体中使用本宏将使之成为最小栈节点结构体
    \param elem_struct_name 栈节点结构体名
    */
    #define MIN_STACK_ITEM_ENTRY(elem_struct_name)              \
    struct                                                      \
    {                                                           \
        struct elem_struct_name * volatile min;                 \
        struct elem_struct_name * volatile next;                \
    }
     
    /*!
    声明最小栈结构体
    \param stack_struct_name 栈结构体名
    \param elem_struct_name 栈节点结构体名
    */
    #define MIN_STACK(stack_struct_name, elem_struct_name)      \
    struct stack_struct_name                                    \
    {                                                           \
        int (* volatile compare)(const struct elem_struct_name*, const struct elem_struct_name *);\
        struct elem_struct_name * volatile top;                 \
    }
     
    /*!
    用比较函数初始化最小化栈指针
    \param stack_ptr 为初始化的栈指针
    \param elem_compare_func 比较函数指针
    */
    #define MIN_STACK_INIT(stack_ptr, elem_compare_func)        \
    do                                                          \
    {                                                           \
        (stack_ptr)->compare = (elem_compare_func);             \
        (stack_ptr)->top = NULL;                                \
    }while(0)
     
    /*!
    最小栈节点初始化
    \param elem_ptr 栈节点指针
    \param elem_entry_name 栈节点中入口成员名
    */
    #define MIN_STACK_ELEM_INIT(elem_ptr, elem_entry_name)      \
    do                                                          \
    {                                                           \
        (elem_ptr)->elem_entry_name.min = (elem_ptr);           \
        (elem_ptr)->elem_entry_name.next = NULL;                \
    }while(0)
     
    /*!
    向最小栈中压入一个节点
    \param stack_ptr 栈指针
    \param elem_ptr 栈节点指针
    \param elem_entry_name 栈节点中入口成员名
    */
    #define MIN_STACK_PUSH(stack_ptr, elem_ptr, elem_entry_name)\
    do                                                          \
    {                                                           \
        if((stack_ptr)->top)                                    \
        {                                                       \
            if((stack_ptr)->compare((stack_ptr)->top->elem_entry_name.min, (elem_ptr)) < 0)\
                (elem_ptr)->elem_entry_name.min = (stack_ptr)->top->elem_entry_name.min;\
        }                                                       \
        (elem_ptr)->elem_entry_name.next = (stack_ptr)->top;    \
        (stack_ptr)->top = (elem_ptr);                          \
    }                                                           \
    while(0)
     
    /*!
    从最小栈中弹出一个节点到elem_ptr
    \param stack_ptr 栈指针
    \param elem_ptr 弹出的栈节点指针
    \param elem_entry_name 栈节点中入口成员名
    */
    #define MIN_STACK_POP(stack_ptr, elem_ptr, elem_entry_name) \
    do                                                          \
    {                                                           \
        elem_ptr = (stack_ptr)->top;                            \
        if((stack_ptr)->top)                                    \
            (stack_ptr)->top = (stack_ptr)->top->elem_entry_name.next;\
    }while(0)
     
    /*!
    获取最小栈中当前最小值(由比较函数确定)
    \param stack_ptr 栈指针
    \param elem_ptr 获取的栈最小节点指针
    \param elem_entry_name 栈节点中入口成员名
    */
    #define MIN_STACK_MIN(stack_ptr, elem_ptr, elem_entry_name) \
        elem_ptr = (stack_ptr)->top->elem_entry_name.min;       \
     
    /*!
    判断栈非空
    \param stack_ptr 栈指针
    */
    #define MIN_STACK_IS_NOT_EMPTY(stack_ptr)                   \
        ((stack_ptr) && (stack_ptr)->top)                       \
     
    struct StackElem                            ///  栈节点结构体
    {
        int entryCanInAnyPosition;              ///< 节点数据
        MIN_STACK_ITEM_ENTRY(StackElem) entry;  ///< 最小栈节点入口
        int data;                               ///< 节点数据
        double otherData;                       ///< 节点数据
    };
     
    MIN_STACK(Stack, StackElem);                ///  栈结构体
     
    /*!
    节点比较函数
    \param elem1 第一个节点指针
    \param elem2 第二个节点指针
    \return 若elem1小于elem2;返回负值;大于返回正值,等于返回0
    */
    int CompareElem(const struct StackElem *elem1, const struct StackElem *elem2)
    {
        assert(elem1 && elem2);
        return elem1->data - elem2->data;
    }
     
    int main()
    {
        int dataSet[] = {5, 6, -2, 3, 4, 2, -1, 3}; //测试数据集
        struct Stack *s = malloc(sizeof(struct Stack));
     
        if(s)
        {
            int i;
     
            MIN_STACK_INIT(s, CompareElem);         //初始化栈
     
            /* 把dataSet数据压入栈 */
            for(i = 0; i < sizeof(dataSet) / sizeof(int); ++i)
            {
                struct StackElem *e = malloc(sizeof(struct StackElem));
     
                if(e)
                {
                    MIN_STACK_ELEM_INIT(e, entry);  //初始化栈节点
     
                    e->data = dataSet[i];
                    e->otherData = -dataSet[i];
     
                    MIN_STACK_PUSH(s, e, entry);    //压入栈节点
     
                    printf("push:%p -> data:%d\n", e, e->data);
                }
            }
     
            /* 把获取当前栈最小值并把栈中数据弹出 */
            while(MIN_STACK_IS_NOT_EMPTY(s))        //循环判断栈非空
            {
                struct StackElem *e = NULL;
                struct StackElem *min = NULL;
     
                MIN_STACK_MIN(s, min, entry);       //获取当前栈的最小节点到min
     
                printf("min: %p -> data:%d\n", min, min->data);
     
                MIN_STACK_POP(s, e, entry);         //弹出栈节点到e
     
                printf("pop: %p -> data:%d\n", e, e->data);
     
                free(e);
            }
        }
     
        printf("%p\n", s);
     
        free(s);
     
        return 0;
    }
  • 相关阅读:
    生产者与消费者
    .net 重新注册
    linux 网络之 bond 网卡模式
    Rancher
    kubernetes 集群
    centos7 网卡命名
    Redis 主从模式
    Redis 集群
    Redis
    TwemProxy Redis架构
  • 原文地址:https://www.cnblogs.com/codingmylife/p/1971238.html
Copyright © 2011-2022 走看看