栈的链式存储结构实现()

18.11.18

学习过之前的顺序的栈了,这回介绍一下链式的栈

我们对栈进行操作时,通常都是在其栈顶进行,所以我们应该在链的头部进行操作,我们之前学过的链表大多是有头结点的,头结点可以大大方便我们对链表的调用,现在,我们的这个链栈可以通过设置一个栈顶指针top来代替头结点,或者说起到头结点的作用

结构定义

链栈有些不同的是,我们需要定义两个结构体,比之前稍增加了点难度,第一个结构体,是用来定义链栈中的每一个结点的(包括top结点)的结构,即StackNode,第二个结构体,是用来定义栈顶指针的,其包含top结点以及一个计数器count,我们通常将第二个结构体命名为LinkStack,因为当我们需要压栈和出栈时,需要调用函数,调用函数时,需要传入参数,一般都是传入栈顶指针来对整个链栈进行操作的,所以直接把栈顶指针命名为LinkStack(即链栈),就应该是它可以代表整个链栈了吧(个人理解)

typedef int SElemType;
//这里将SElemType等同于int,实际运用中数据不一定是int的,可以改变

typedef struct StackNode{//这里设置链栈的结点结构
    //每个结点包含一个数据域和一个指针域
    SElemType data;
    struct StackNode *next;
}StackNode,*pNode;//*pNode是结点的结构体指针

typedef struct LinkStack{//这里设置栈顶指针
//包含了top结点的地址和一个计数器count
    pNode top;
    int count;
}LinkStack;

链栈初始化

跟链表很像,链表是头结点指向NULL,这里是top结点指向NULL,同时将计数器置0

void InitStack(LinkStack *ST){//初始化函数
    ST->top=NULL;//top结点指向空
    ST->count=0;//置0
}

压栈(入栈)

现在是只有栈顶指针的空栈,我们要加入一下元素,就要压栈
思路是创造一个新的结点,将要加入的数据存入里面,在将新结点压入就行了,具体代码如下

void Insert(LinkStack *ST,SElemType e){//将栈顶指针地址和将要入栈的元素传入
    pNode s=(pNode)malloc(sizeof(StackNode));//给新结点分配空间
    s->data=e;
    s->next=ST->top;
    ST->top=s;
    ST->count++;//每压入一个元素,栈的计数器加1
}

出栈

我们不仅要给函数传入一个栈顶指针地址,还要传入一个整型指针的地址来保存弹出的元素,记得事后将弹出的结点free掉

int Pop(LinkStack *ST,SElemType *e){
    pNode p;//创造一个结点p,用于存储要弹出结点的地址
    if(ST->count==0)//如果是空栈就不能弹出了
        return 0;
    p=ST->top;//存入要弹出的地址
    *e=ST->top->data;//保存要弹出的元素
    ST->top=ST->top->next;//栈顶指针向后指
    ST->count--;//计数器减1
    free(p);//释放掉弹出结点的空间
    return 1;
}

打印栈

需要一个定位指针,通过其遍历整个链栈,打印遍历到的每个结点的data域上的值

int Print(LinkStack *ST){//打印函数
    pNode H=ST->top;//定位指针
    if(H==NULL)//如果定位指针都是指向空的,说明没什么好打印的了
        return 0;
    printf("此时栈为:  ");
    printf("%d  ",H->data);
    while(H->next!=NULL){
        H=H->next;
        printf("%d  ",H->data);
    }
    printf("\n");
    return 1;
}

源程序

将上述的函数合并起来进行调试

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>

typedef int SElemType;

typedef struct StackNode{//这里设置链栈的结点结构
    //每个结点包含一个数据域和一个指针域
    SElemType data;
    struct StackNode *next;
}StackNode,*pNode;//*pNode是结点的结构体指针

typedef struct LinkStack{//这里设置栈顶指针
    pNode top;
    int count;
}LinkStack;

//函数声明
void InitStack(LinkStack *ST);
void Insert(LinkStack *ST,SElemType e);
int Pop(LinkStack *ST,SElemType *e);
int Print(LinkStack *ST);


int main(){//主函数调试
    LinkStack ST;
    int i,e;
    InitStack(&ST);
    for(i=0;i<10;i++){
        Insert(&ST,i);
    }
        Print(&ST);
    for(i=0;i<5;i++){
        Pop(&ST,&e);
        printf("弹出了一个数字%d,",e);
        Print(&ST);
        printf("\n");
    }
    Print(&ST);
}

void InitStack(LinkStack *ST){//初始化函数
    ST->top=NULL;//top结点指向空
    ST->count=0;//置0
}

void Insert(LinkStack *ST,SElemType e){//将栈顶指针地址和将要入栈的元素传入
    pNode s=(pNode)malloc(sizeof(StackNode));//给新结点分配空间
    s->data=e;
    s->next=ST->top;
    ST->top=s;
    ST->count++;//每压入一个元素,栈的计数器加1
}

int Pop(LinkStack *ST,SElemType *e){
    pNode p;//创造一个结点p,用于存储要弹出结点的地址
    if(ST->count==0)//如果是空栈就不能弹出了
        return 0;
    p=ST->top;//存入要弹出的地址
    *e=ST->top->data;//保存要弹出的元素
    ST->top=ST->top->next;//栈顶指针向后指
    ST->count--;//计数器减1
    free(p);//释放掉弹出结点的空间
    return 1;
}

int Print(LinkStack *ST){//打印函数
    pNode H=ST->top;//定位指针
    if(H==NULL)//如果定位指针都是指向空的,说明没什么好打印的了
        return 0;
    printf("此时栈为:  ");
    printf("%d  ",H->data);
    while(H->next!=NULL){
        H=H->next;
        printf("%d  ",H->data);
    }
    printf("\n");
    return 1;
}

调试结果
在这里插入图片描述
成功啦!!

总结

  • 链栈跟链表很像
  • 创建使一定要记清楚自己写的结构体里边到底包含了什么!!!
  • 自己给它起的什么名字!!!
  • 永远要清楚自己的指针指向了什么地方!!!

猜你喜欢

转载自blog.csdn.net/qq_43604992/article/details/84197465