数据结构和算法-栈结构

460 阅读2分钟

栈的定义

栈是一种后进先出的数据结构。

栈是限制插入和删除只能在一个位置上的线性表。允许删除和插入的一端位于表的末端,叫做栈顶。不允许删除和插入的另一端叫做栈底。对栈的基本操作有push(压栈)和pop(出栈)。

图示:

栈的实现

栈的实现主要包括两种方式:顺序栈和链表栈。

顺序栈

使用数组来实现。

缺点: 需要提前声明一个数组大小。如果数组不够大,就有可能发生越界问题。如果数组过大,则可能浪费一定的空间。

栈的定义实现:

typedef int Status;
typedef int ElemType;

typedef struct{
    ElemType data[MAXSIZE];
    int top;
}SqStack;

初始化一个空栈

Status InitStack(SqStack *S){
    S->top = -1;
    return OK;
}

将栈置空

Status ClearStack(SqStack *S){
    S->top = -1;
    return OK;
}

判断栈是否为空

Status IsEmptyStack(SqStack S){
    if (S.top == -1) {
        return TRUE;
    }
    return FALSE;
}

获取栈的长度

int LengthOfStack(SqStack S){
    if(IsEmptyStack(S)) return ERROR;
    return S.top + 1;
}

栈顶的值

Status ValueOfStack(SqStack S, ElemType *topValue){
    if(IsEmptyStack(S)) return ERROR;
    *topValue = S.data[S.top];
    return OK;
}

栈中插入元素

Status PushStack(SqStack *S, ElemType e){
    
    if (S->top == MAXSIZE -1) {
        return ERROR;
    }
    S->top++;
    S->data[S->top] = e;
    
    return OK;
}

栈中删除栈顶元素

Status PopStack(SqStack *S, ElemType *e){
    if (S->top == -1) {
        return ERROR;
    }
    
    *e = S->data[S->top];
    S->top -- ;
    return OK;
}

遍历打印栈元素

void PrintStack(SqStack S){
    printf("打印顺序栈:\n");
    while (S.top > -1) {
        printf("%d  ",S.data[S.top]);
        S.top -- ;
    }
    printf("\n");
}

以上是顺序栈的基本操作。下面讲下链式栈。

链式栈

使用链表来实现栈。内存动态分配,可以不担心内存分配的问题,但是要考虑malloc和free的调用.

链式栈和顺序栈稍有不同,定义链式栈的时候要先定一个链式栈的结构。

typedef struct StackNode{
    ElemType data;
    struct StackNode *next;
}StackNode,*LinkStackPtr;

typedef struct
{
    LinkStackPtr top;
    int count;
}LinkStack;

初始化一个空栈

Status InitStack(LinkStack *S){
    S->top = NULL;
    S->count = 0;
    return OK;
}

把栈置空

Status ClearStack(LinkStack *S){
    //链式栈就要考虑free的问题了
    LinkStackPtr p,q;
    p = S->top;
    while (p) {
        q = p;
        p = p->next;
        free(q);
    }
    //上面已经把S->top变成null了
//    S->top = NULL;
    S->count = 0;
    return OK;
}

是否为空栈

Status IsEmptyLinkStack(LinkStack S){
    if (S.count) {
        return FALSE;
    }
    return OK;
}

栈中元素的个数

int LengthOfLinkStack(LinkStack S){
    return S.count;
}

获取栈顶元素

Status TopValueOfLinkStack(LinkStack S, ElemType *e){
    
    if (IsEmptyLinkStack(S)) return ERROR;
    *e = S.top->data;
    return OK;
}

压栈(插入)

Status PushLinkStack(LinkStack *S, ElemType data){
    LinkStackPtr p = (LinkStackPtr)malloc(sizeof(StackNode));
    p->data = data;
    p->next = S->top;
    S->top = p;
    S->count ++;
    return OK;
}

出栈(删除栈顶)

Status PopLinkStack(LinkStack *S, ElemType *data){
    LinkStackPtr p;
    if (IsEmptyLinkStack(*S)) {
        return ERROR;
    }
    
    *data = S->top->data;
    p = S->top->next;
    S->top = p;
    S->count -- ;
    
    free(p);
    return OK;
}

遍历栈元素

void printLinkStack(LinkStack S){
    printf("打印链式栈!\n");
    LinkStackPtr p;
    p = S.top;
    while (p) {
        printf("%d  ",p->data);
        p = p->next;
    }
    printf("\n");
}

以上为链式栈的基本操作。