目录
一、栈基础知识
在平时开发中,栈是一种非常常见的数据结构,例如函数调用、系统中断、表达式求值,相信每一个做开发的小伙伴,不管使用语言为何种,肯定都自己写过或用过这样的数据结构。栈就是一种“操作受限”的后进先出的线性表,只允许在一端插入和删除数据;所以栈的操作相对数据和链表就比较简单了,主要为入栈 和 出栈 操作,也就是在栈顶插入一个数据和在栈顶删除一个数据。
那么如何实现一个栈呢?实际上,可以通过两种方式来实现,一种是用数组来实现的顺序栈,和使用链表来实现的链式栈。不管基于数组还是链表,入栈、出栈的时间复杂度都为 O(1)
- A:为什么函数调用要用“栈”来保存临时变量呢?用其他数据结构不行吗?
- Q:从调用函数进入被调用函数,对于数据来说,变化的是什么呢?是作用域。所以根本上,只要能保证每进入一个新的函数,都是一个新的作用域就可以。而要实现这个,用栈就非常方便。在进入被调用函数的时候,分配一段栈空间给这个函数的变量,在函数结束的时候,将栈顶复位,正好回到调用函数的作用域内。
二、顺序栈数据结构
#define ARRAY_STACK_SIZE(pstack) (pstack->size)
#define ARRAY_STACK_IS_EMPTY(pstack) (pstack->pos == -1)
#define ARRAY_STACK_IS_FULL(pstack) (pstack->pos == (pstack->size - 1))
struct array_stack
{
int size; /* stack total size */
int pos; /* stack cur position rang:-1 -- (size-1)*/
int tpsz; /* data type size */
void *p; /* stack space */
};
二、顺序栈增删改查函数声明
extern struct array_stack* array_stack_creat(int size, int tpsz);
extern int array_stack_init (struct array_stack *stack, int size, int tpsz);
extern int array_stack_empty (struct array_stack *stack);
extern int array_stack_destory(struct array_stack *stack);
extern int array_stack_pop (struct array_stack *stack, void *out_data);
extern int array_stack_push(struct array_stack *stack, void *in_data);
extern int array_stack_push_dyn(struct array_stack *stack, void *in_data);
extern void array_stack_test(void);
三、创建顺序栈
1、栈头部动态创建
/**
* dynamically creat and init an array stack.
*
* @param size: array size
* @param tpsz: data type size
* @return result: array stack or NULL
*/
struct array_stack* array_stack_creat(int size, int tpsz)
{
struct array_stack *stack = NULL;
if (size <= 0 || tpsz <= 0)
return NULL;
/* malloc an array stack struct */
stack = ARRAY_STACK_MALLOC(sizeof(*stack));
if (stack == NULL)
return NULL;
/* calloc an array stack */
void *p = ARRAY_STACK_CALLOC(1, (size * tpsz));
if (p == NULL)
return NULL;
stack->size = size;
stack->tpsz = tpsz;
stack->pos = -1;
stack->p = p;
return stack;
}
2、栈头部静态创建
/**
* init a static array stack.
*
* @param stack:
* @param size: array size
* @param tpsz: array data type length
* @return -1:stack is null or malloc fail
* 0:success
*/
int array_stack_init(struct array_stack *stack, int size, int tpsz)
{
if (stack == NULL)
return -1;
/* calloc an array stack */
void *p = ARRAY_STACK_CALLOC(1, (size * tpsz));
if (p == NULL)
return NULL;
stack->size = size;
stack->tpsz = tpsz;
stack->pos = -1;
stack->p = p;
return 0;
}
四、出栈
/**
* pop data from the array stack.
*
* @param array_stack: array stack
* @return -1: fail
* -2: stack is empty
* 0: success
*/
int array_stack_pop(struct array_stack *stack, void *out_data)
{
char *pbegin = NULL;
void *data = NULL;
if (stack == NULL)
return -1;
/* stack is empty */
if(ARRAY_STACK_IS_EMPTY(stack))
return -2;
pbegin = stack->p;
data = pbegin + stack->tpsz * stack->pos;
memcpy(out_data, data, stack->tpsz);
stack->pos--;
return 0;
}
五、入栈
1、不支持动态扩容
/**
* push data to the array stack.
*
* @param array_stack: array stack
* @return -1: fail
* -2: stack is full
* 0: success
*/
int array_stack_push(struct array_stack *stack, void *in_data)
{
char *pbegin = NULL;
void *data = NULL;
if (stack == NULL)
return -1;
/* stack is full */
if(ARRAY_STACK_IS_FULL(stack))
return -2;
pbegin = stack->p;
stack->pos++;
data = pbegin + stack->tpsz * stack->pos;
memcpy(data, in_data, stack->tpsz);
return 0;
}
2、支持替代扩容
/**
* Support dynamic expansion of sequential stack,
* when the stack is full to reapply for 2 times the size of the stack space.
*
* @param array_stack: array stack
* @return -1: fail
* -2: stack is full
* 0: success
*/
int array_stack_push_dyn(struct array_stack *stack, void *in_data)
{
void *new_p = NULL;
if (stack == NULL)
return -1;
/* stack is full */
if(ARRAY_STACK_IS_FULL(stack))
{
new_p = ARRAY_STACK_CALLOC(1, (2 * stack->size * stack->tpsz));
if (new_p == NULL)
return -1;
memcpy(new_p, stack->p, stack->size * stack->tpsz);
ARRAY_STACK_FREE(stack->p);
stack->p = new_p;
stack->size *= 2;
return array_stack_push(stack, in_data);
}
else
{
return array_stack_push(stack, in_data);
}
}
六、栈删除
/**
* delete array stack space.
*
* @param array_stack: array stack
* @return -1: fail
* 0:success
*/
int array_stack_empty(struct array_stack *stack)
{
if (stack == NULL)
return -1;
/* free array stack space */
if (stack->p != NULL)
{
ARRAY_STACK_FREE(stack->p);
stack->p = NULL;
}
return 0;
}
七、栈销毁
/**
* delete and destroy an array stack.
*
* @param array_stack: array stack
* @return -1: fail
* 0:success
*/
int array_stack_destory(struct array_stack *stack)
{
if (array_stack_empty(stack) != 0)
return -1;
ARRAY_STACK_FREE(stack);
stack = NULL;
return 0;
}
八、验证程序
struct array_stack *array_stack_head;
int array_stack_w[5] = {11,22,33,44,55};
int array_stack_r[5] = {0};
void array_stack_test(void)
{
array_stack_head = array_stack_creat(5, sizeof(int));
array_stack_push(array_stack_head, (void*)&array_stack_w[0]);
array_stack_push(array_stack_head, (void*)&array_stack_w[1]);
array_stack_push(array_stack_head, (void*)&array_stack_w[2]);
array_stack_push(array_stack_head, (void*)&array_stack_w[3]);
array_stack_push(array_stack_head, (void*)&array_stack_w[4]);
array_stack_pop(array_stack_head, (void*)&array_stack_r[0]);
array_stack_pop(array_stack_head, (void*)&array_stack_r[1]);
array_stack_pop(array_stack_head, (void*)&array_stack_r[2]);
array_stack_pop(array_stack_head, (void*)&array_stack_r[3]);
array_stack_pop(array_stack_head, (void*)&array_stack_r[4]);
array_stack_push(array_stack_head, (void*)&array_stack_w[0]);
array_stack_pop(array_stack_head, (void*)&array_stack_r[0]);
array_stack_push(array_stack_head, (void*)&array_stack_w[1]);
array_stack_pop(array_stack_head, (void*)&array_stack_r[1]);
array_stack_push(array_stack_head, (void*)&array_stack_w[2]);
array_stack_pop(array_stack_head, (void*)&array_stack_r[2]);
array_stack_push(array_stack_head, (void*)&array_stack_w[3]);
array_stack_pop(array_stack_head, (void*)&array_stack_r[3]);
array_stack_push(array_stack_head, (void*)&array_stack_w[4]);
array_stack_pop(array_stack_head, (void*)&array_stack_r[4]);
}