练习系列 - 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;
}
posted @ 2011-03-04 21:22  紫红的泪  阅读(1889)  评论(0编辑  收藏  举报