一、个人理解
栈是线性表的一种衍生,和之前的顺序表和链表在插入和删除元素上有较大差异,其他基本相同,栈是数据只能插入表的尾部(栈顶),删除数据时只能删除表的尾部(栈顶)数据,就是大家经常背的顺口溜:后入先出。后插入的数据先删除。
二、图解
 
   这里把数组竖起来了,是方便理解,看得更清楚。
三、名词解释
1、出栈、弹栈
是一个意思,就是把数据从栈顶移除。
2、入栈、压栈
是一个意思,就是把数据从栈顶插入。
3、LIFO
LAST IN FIRST OUT的简写,也就是后进先出的意思。
4、顺序栈和链栈
实现方式上的不同,顺序栈是用数组实现,而链栈是用链表实现。
5、上溢
栈已满,但数据还需要继续入栈。上溢一般认为是一种错误,因为可能导致数据录入失败,或者导致数据录入延时。当是顺序栈时,对此情况有两种措施:
一是抛出错误。
二是重新申请新栈,把旧栈数据写入到新栈中,不推荐,比较耗时。
6、下溢
栈已空,但还是要出栈。下溢一般认为是一种结束标志,因为并不会有数据上的缺失。
四、函数实现
1、InitSqStack
(1)用途
初始化顺序栈。
(2)源码
Status InitSqStack(SqStack* S)
{
    printf("Init SqStack  : ");
    JudgeAllNullPointer(S);
    S->BasePointer    = (SqElemType*)MyMalloc(sizeof(SqElemType) * SQ_STACK_MAX_SIZE);
    S->TopPointer     = S->BasePointer;
    S->SqStackMaxSize = SQ_STACK_MAX_SIZE;
    printf("OK\n");
    PrintPretty();
    return SuccessFlag;   
}(3)参数
| 参数名 | 说明 | 
| S | 需要初始化的SqStack*类型顺序栈。 | 
2、JudgeSqStackIsEmpty
(1)用途
判断顺序栈是否为空。
当栈顶指针和栈底指针相等时,表示栈为空,反之非空。
(2)源码
Status JudgeSqStackIsEmpty(SqStack* S)
{
    printf("Judge SqStack : ");
    JudgeAllNullPointer(S);
    if(S->BasePointer == S->TopPointer)
    {
        printf("Empty\n");
        PrintPretty();
        return SuccessFlag;
    }
    printf("Not Empty\n");
    PrintPretty();
    return FailFlag;
}(3)参数
| 参数名 | 说明 | 
| S | 需要判断是否为空的SqStack*类型顺序栈。 | 
3、GetSqStackLen
(1)用途
求顺序栈的长度。
栈顶指针减去栈底指针为顺序栈的长度,原理为相同类型的指针相减得到字节数,它会再除以一个栈类型(头文件中的结构体SqElemType)的字节长度,得到最终的顺序栈的长度。
(2)源码
SqStackMaxSizeType GetSqStackLen(SqStack* S)
{
    JudgeAllNullPointer(S);
    return S->TopPointer - S->BasePointer;
}(3)参数
| 参数名 | 说明 | 
| S | 需要求栈长度的SqStack*类型顺序栈。 | 
五、测试代码
1、SqStack.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include "SqStack.h"
void PrintPretty()
{
    printf("*********************************\n");
}
void PrintPretty_V1()
{
    printf("################\n");
}
void *MyMalloc(size_t size)
{
    void *Result = (void *)malloc(size);
    if(Result == NULL)
    {
        printf("malloc Function Exec Fail , Out Of Memory ,Exit!!!\n");
        exit(ExceptionExitFlag);
    }
    return Result;
}
void JudgeAllNullPointer(void* P)
{
    if(!P)
    {
        printf("Pointer Is Null ,Exit !\n");
        exit(ExceptionExitFlag);
    }
}
Status InitSqStack(SqStack* S)
{
    printf("Init SqStack  : ");
    JudgeAllNullPointer(S);
    S->BasePointer    = (SqElemType*)MyMalloc(sizeof(SqElemType) * SQ_STACK_MAX_SIZE);
    S->TopPointer     = S->BasePointer;
    S->SqStackMaxSize = SQ_STACK_MAX_SIZE;
    printf("OK\n");
    PrintPretty();
    return SuccessFlag;   
}
Status JudgeSqStackIsEmpty(SqStack* S)
{
    printf("Judge SqStack : ");
    JudgeAllNullPointer(S);
    if(S->BasePointer == S->TopPointer)
    {
        printf("Empty\n");
        PrintPretty();
        return SuccessFlag;
    }
    printf("Not Empty\n");
    PrintPretty();
    return FailFlag;
}
SqStackMaxSizeType GetSqStackLen(SqStack* S)
{
    JudgeAllNullPointer(S);
    return S->TopPointer - S->BasePointer;
}2、SqStack.h
#ifndef SqStack_H
#define SqStack_H
#define InsertDataArrayLen 8
#define SQ_STACK_MAX_SIZE  6
#define ExceptionExitFlag -1
#define SuccessFlag        1
#define FailFlag           0
#define StudentNumLen      8
#define StudentNameLen     8
typedef int Status;
typedef long long int SqStackMaxSizeType;
typedef struct SqElemType
{
    char StudentNum[StudentNumLen];
    char StudentName[StudentNameLen];
    int  StudentScore;
}SqElemType;
typedef struct 
{
    SqElemType*        BasePointer;
    SqElemType*        TopPointer;
    SqStackMaxSizeType SqStackMaxSize;
}SqStack;
void *MyMalloc(size_t size);
void JudgeAllNullPointer(void* P);
void PrintPretty();
void PrintPretty_V1();
Status InitSqStack(SqStack* S);
Status JudgeSqStackIsEmpty(SqStack* S);
SqStackMaxSizeType GetSqStackLen(SqStack* S);
#endif3、main.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "SqStack.h"
int main()
{
    //测试数据生成
    SqElemType *InsertSqElemArray = (SqElemType *)MyMalloc(sizeof(SqElemType) * InsertDataArrayLen);
    int i;
    for(i=0; i<InsertDataArrayLen; i++)
    {
        strcpy(InsertSqElemArray[i].StudentNum ,"X666");
        strcpy(InsertSqElemArray[i].StudentName,"Sun");
        InsertSqElemArray[i].StudentScore = i + 100;
    }
    //测试顺序栈
    SqStack* S = (SqStack*)MyMalloc(sizeof(SqStack));
    InitSqStack(S);
    JudgeSqStackIsEmpty(S);
    printf("SqStack Len   : %lld\n",GetSqStackLen(S));
    PrintPretty();
    //释放内存
    free(InsertSqElemArray);
    InsertSqElemArray = NULL;
    return SuccessFlag;
}4、makefile
CC = gcc
CFLAG_EXEC = -Wall -O3
CFLAG_ALIAS = -o
RM_COMM = rm -rf
all : main
main : 
    $(CC) $(CFLAG_EXEC) SqStack.c main.c $(CFLAG_ALIAS) TestSqStack
clean : 
    $(RM_COMM) TestSqStack六、测试结果
[gbase@czg2 LinearTable_Stack]$ make clean
rm -rf TestSqStack
[gbase@czg2 LinearTable_Stack]$ make
gcc -Wall -O3 SqStack.c main.c -o TestSqStack
[gbase@czg2 LinearTable_Stack]$ ./TestSqStack 
Init SqStack  : OK
*********************************
Judge SqStack : Empty
*********************************
SqStack Len   : 0
*********************************七、顺序栈的应用
大家可以参考一下之前写的文章《leecode-C语言实现-20. 有效的括号》,里面用到了顺序栈的知识。



















