stack:是一种的后进先出的线性数据结构,其操作一端是受限的,即只能从栈顶操作。
通常,其实实现可以有动态数组实现,也可以由链表实现,似乎链表实现更合理。
同过数组实现的栈的一个好处,可以是栈想数组那样随机的访问stack中的元素,而且通过预留量不用频繁的内存分配操作。
本文,针对stack 实现一种用C语言实现的动态数组栈。栈的容积可以随栈中元素的个数,将其容量自动增减,本文实现的调节因子是2.
实现代码如下:
1.实现的接口文件:stack.h
#ifndef STACK_H
#define STACK_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
/* initial stack capacity in terms of elements */
#define STACK_INITIAL_SIZE 1 // 1 未测试使用,其值可以根据具体的需求定。
#define CHECK_MEM(p) \
if ((p) == NULL) { \
fprintf(stderr, "out of memory: in file %s, line %d, function %s.\n", __FILE__, __LINE__, __FUCTION__); \
exit(1); \
}
typedef struct stack_t {
void *base;
void *top;
int element_size; /* element size */
unsigned int capacity; /* stack capacity in byte */
} stack;
/* stack operations */
void stack_init(stack *stack, int element_size);
void stack_free(stack *stack);
int stack_empty(stack *stack);
int stack_size(stack *stack);
void stack_push(stack *stack, void *element);
void* stack_pop(stack *stack);
/* clear elements to make stack empty, but don't free memory */
void stack_clear(stack *stack);
/* copy contents of stack x to stack y; y must have been initiated and not freed */
void stack_copy(stack *x, stack *y);
#endif /* STACK_H */
2. stack功能实现文件:stack.c
#include "stack.h"
/* stack operations */
void stack_init(stack *stack, int element_size) {
stack->base = (void *) malloc(STACK_INITIAL_SIZE * element_size);
if (stack->base == NULL) {
fprintf(stderr, "out of memory (in file %s : line %d : fuction %s.)\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
stack->element_size = element_size;
stack->capacity = STACK_INITIAL_SIZE * element_size;
stack->top = stack->base;
}
void stack_free(stack *stack) {
if (stack->base != NULL) {
free(stack->base);
stack->base = NULL;
}
stack->element_size = 0;
stack->capacity = 0;
stack->top = NULL;
}
int stack_empty(stack *stack) {
assert(NULL != stack);
assert(stack->top >= stack->base);
return (stack->top == stack->base) ? 1 : 0;
}
int stack_size(stack *stack) {
assert(NULL != stack);
assert(stack->top >= stack->base);
return (stack->top - stack->base) / stack->element_size;
}
void stack_push(stack *stack, void *element) {
if(stack->top == (stack->base + stack->capacity)) {
void *base;
int n = stack->capacity;
stack->capacity <<= 1;
base = (void *) realloc(stack->base, stack->capacity);
if (base == NULL) {
fprintf(stderr, "out of memory (in file %s : line %d : fuction %s.)\n", __FILE__, __LINE__, __FUNCTION__);
stack_free(stack);
exit(1);
}
// if(stack->base) printf("stack base: %p; base: %p\n", stack->base, base);
stack->base = base;
stack->top = base + n;
}
memcpy(stack->top, element, stack->element_size);
stack->top += stack->element_size;
}
void* stack_pop(stack *stack) {
if (stack_empty(stack)) {
return NULL;
}
if((stack->top - stack->base) > STACK_INITIAL_SIZE && (stack->top - stack->base) < (stack->capacity >> 1)) {
void *base;
stack->capacity >>= 1;
base = (void *) realloc(stack->base, stack->capacity);
if (base == NULL) {
fprintf(stderr, "memory relloca error:(in file %s : line %d : fuction %s.)\n", __FILE__, __LINE__, __FUNCTION__);
stack_free(stack);
exit(1);
}
// if(stack->base) printf("stack base: %p; base: %p\n", stack->base, base);
stack->base = base;
// printf("pop\n");
}
stack->top -= stack->element_size;
return stack->top;
}
/* clear elements to make stack empty, but don't free memory */
void stack_clear(stack *stack) {
stack->top = stack->base;
}
/* copy contents of stack x to stack y; y must have been initiated and not freed */
void stack_copy(stack *x, stack *y) {
assert(NULL!=x && NULL!=y);
/* first free stack y */
stack_free(y);
y->base = (void *) malloc(x->capacity);
if (y->base == NULL) {
fprintf(stderr, "out of memory (in file %s : line %d : fuction %s.)\n", __FILE__, __LINE__, __FUNCTION__);
stack_free(x);
exit(1);
}
int len = x->top - x->base;
memcpy(y->base, x->base, len);
y->element_size = x->element_size;
y->capacity = x->capacity;
y->top = y->base + len;
}
3.测试stack的文件:main.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "stack.h"
void printArray(int a[], int len);
int main(int argc, char* argv[])
{
int a[] = {1, 2, 3, 4, 5, 6, 7, 8};
int len = sizeof(a) / sizeof(a[0]);
int i;
stack stack;
printArray(a, len);
stack_init(&stack, sizeof(a[0]));
//printf("%d\n", stack_size(&stack));
for(i = 0; i < len; ++i) {
stack_push(&stack, &a[i]);
}
//printf("%d\n", stack_size(&stack));
//printf("%d\n", stack.capacity);
while(!stack_empty(&stack)) {
printf("%d\t", *(int *)stack_pop(&stack));
}
printf("\n");
//printf("%d\n", stack.capacity);
//printf("%d\n", stack_size(&stack));
stack_free(&stack);
return 0;
}
void printArray(int a[], int len) {
int i;
for(i=0; i<len; i++) {
printf("%d\t", a[i]);
}
printf("\n");
}
测试输出: