No.
2022-12-29
  • Jan
  • Feb
  • Mar
  • Apr
  • May
  • Jun
  • Jul
  • Aug
  • Sep
  • Oct
  • Nov
  • Dec
  • Sun
  • Mon
  • Tue
  • Wed
  • Thu
  • Fri
  • Sat
  • 28
  • 29
  • 30
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

用数组实现栈

栈定义

栈是一种特殊的线性表,它只允许在表的一端进行操作,遵循先进后出(FILO, First In Last Out)的原则,可以操作的一端称为栈顶,不可以操作的一端称为栈底。向栈中加入数据叫入栈,从栈中取出数据叫做出栈。数据结构及操作如图所示:

stack.png

栈实现

栈可以使用数组或链表来实现,这里用数组实现。

数据结构定义:

typedef struct {
    unsigned int stackTop;    //栈顶索引
    unsigned int stackSize;    //栈大小
    char *stackArray;
}ttStack;

栈初始化及销毁:

//错误码定义
#define STACK_RESIZE_OK    (1)
#define STACK_OK    (0)
#define STACK_INIT_ERR    (-1)
#define STACK_RESIZE_ERR    (-2)
#define STACK_PUSH_ERR    (-3)

#define STACK_LENGTH    (16)

//栈初始化
ttStack* stackInit()
{
    ttStack *stack = NULL;
    stack = (ttStack *) malloc (sizeof(ttStack));
    if (stack == NULL)
        return NULL;
    stack->stackTop = 0;
    stack->stackSize = STACK_LENGTH;
    stack->stackArray = (char*)malloc(sizeof(char) * STACK_LENGTH);
    if (stack->stackArray == NULL) {
        free(stack);
        return NULL;
    }
    return stack;
}

//销毁栈
void stackDestory(ttStack* stack)
{
    if (stack != NULL) {
        if (stack->stackArray != NULL) {
            free(stack->stackArray);
            stack->stackArray = NULL;
        }
        free(stack);
        stack = NULL;
    }
}

栈调用 stackInit 进行初始化,先申请一个 STACK_LENGTH 大小的数组,当栈容量不够时会调用 pushCheckAndResize 对栈进行扩容,与 c++ 中 vector 扩容方式相同,每次容量扩为原来的 2 倍。栈销毁时要将对应的内存进行释放。

static int pushCheckAndResize(ttStack* stack, unsigned int pushSize)
{
    unsigned int nowSize = stack->stackSize;
    if (stack->stackTop + pushSize <= nowSize)
        return STACK_OK;

    while (stack->stackTop + pushSize > nowSize)
        nowSize *= 2;

    printf("resize Stack %d, need:%d\n", nowSize, stack->stackTop + pushSize);
    char* tmpArray = (char *) malloc (nowSize * sizeof(char));
    if (tmpArray == NULL)
        return STACK_RESIZE_ERR;

    memcpy(tmpArray, stack->stackArray, stack->stackTop * sizeof(char));
    free(stack->stackArray);
    stack->stackArray = tmpArray;
    stack->stackSize = nowSize;

    return STACK_OK;
}

栈最重要的操作就是入栈和出栈,下面是对数据类型是 int 的数据进行入栈和出栈的操作:

//int 入栈
int pushInt(ttStack* stack, int data)
{
    if (stack == NULL || stack->stackArray == NULL) {
        printf("please init stack first\n");
        return STACK_INIT_ERR;
    }
    if (pushCheckAndResize(stack, sizeof(int)) != STACK_OK)
        return STACK_PUSH_ERR;
    *((int *)(&stack->stackArray[stack->stackTop])) = data;
    stack->stackTop += sizeof(int);
    return STACK_OK;
}

//int 出栈
int popInt(ttStack* stack)
{
    if (stack == NULL || stack->stackArray == NULL || stack->stackTop < sizeof(int))
        return (int)STACK_INIT_ERR;
    stack->stackTop -= sizeof(int);
    int a = *((int *)(&stack->stackArray[stack->stackTop]));
    return a;
}

其它数据类型与 int 类型基本相同,因此可用宏定义来定义不同数据类型的函数:

//入栈函数宏
int push##funcName(ttStack* stack, type data)    \
{    \
    if (stack == NULL || stack->stackArray == NULL) {    \
        printf("please init stack first\n");    \
        return STACK_INIT_ERR;    \
    }    \
    if (pushCheckAndResize(stack, sizeof(type)) != STACK_OK)    \
        return STACK_PUSH_ERR;    \
    *((type *)(&stack->stackArray[stack->stackTop])) = data;    \
    stack->stackTop += sizeof(type);    \
    return STACK_OK;    \
}
//出栈函数宏
#define implementPopFunction(funcName, type)    \
type pop##funcName(ttStack* stack)    \
{    \
    if (stack == NULL || stack->stackArray == NULL || stack->stackTop < sizeof(type))    \
        return (type)STACK_INIT_ERR;    \
    stack->stackTop -= sizeof(type);    \
    type a = *((type *)(&stack->stackArray[stack->stackTop]));    \
    return a;    \
}

//入栈函数
//char
implementPushFunction(Char, char)
//short
implementPushFunction(Short, short)
//int
implementPushFunction(Int, int)
//long
implementPushFunction(Long, long)
//指针
implementPushFunction(Ptr, void*)
//float
implementPushFunction(Float, float)
//double
implementPushFunction(Double, double)

//出栈函数
//char
implementPopFunction(Char, char)
//short
implementPopFunction(Short, short)
//int
implementPopFunction(Int, int)
//long
implementPopFunction(Long, long)
//指针
implementPopFunction(Ptr, void*)
//float
implementPopFunction(Float, float)
//double
implementPopFunction(Double, double)

测试函数:

int main(int argc, char* argv[])
{
    char a = 'a';
    short b = 10;
    int c = 1024;
    long d = 10000;
    int array[] = { 1, 2, 3, 4, 5 };

    printf("array:%p\n", array);

    ttStack* stack = stackInit();

    pushChar(stack, a);
    pushShort(stack, b);
    pushInt(stack, c);
    pushLong(stack, d);
    pushPtr(stack, array);

    //必须按逆序出栈
    int* ptr = (int*)popPtr(stack);
    long dd = popLong(stack);
    int cc = popInt(stack);
    short bb = popShort(stack);
    char aa = popChar(stack);

    printf("pop:%c, %d, %d, %d, %p\n", aa, bb, cc, dd, ptr);

    stackDestory(stack);
    return 0;
}