栈的理解与实现[数据结构]

一.栈的定义

Tips:阅读本文之前,请先熟悉链表知识:链表的理解与实现

栈是一种可以实现”先进后出“的数据结构。
栈只允许在栈顶进行插入、删除、遍历等操作。
如下图:
依次放入 5-6-7 到栈内。
拿出 6来,得先拿出 7来
拿出 5来,得先拿出7、6来。
也就是7后进的,7先出栈;5先进的,5后出栈。
这里写图片描述


二、栈的实现

1.初始化一个栈

1.1定义链表的节点结构

typedef struct Node
{
    int data;
    struct Node * pNext;
}NODE,*PNODE;

1.2定义栈的首指针与尾指针

typedef struct stack
{
    PNODE pTop;  //栈顶指针
    PNODE pBottom;//栈底指针
}STACK,*PSTACK;

1.3初始化一个栈

//初始化一个栈
void initStack(PSTACK pS)
{
    pS->pTop=(PNODE)malloc(sizeof(NODE));
    if(pS->pTop==NULL)
    {
        printf("栈初始化失败\n");
        exit(-1);
    }
    else
    {
        pS->pBottom=pS->pTop;
        pS->pBottom->pNext=NULL;
    }
}

如果此栈初始化成功,会有如下图示的结构:
这里写图片描述

2.压栈

压栈就是在栈顶压入一个元素。
压栈分为3步:
1.创建一个新节点存放数值;
2.使新节点指向pTop指向的元素;
3.使pTop指向新元素。

代码实现:

//压栈
void pushStack(PSTACK pS,int val)
{
    //1.创建一个新节点存放数值;
    PNODE pNew=(PNODE)malloc(sizeof(NODE));
    pNew->data=val;
    //2.使新节点指向pTop指向的元素;
    pNew->pNext=pS->pTop;
    //3.使pTop指向新元素。
    pS->pTop=pNew;
}

如图:
压栈前:
这里写图片描述
压栈后
这里写图片描述

3.遍历栈

3.1判断栈是否为空(空则不遍历,直接返回)

当栈顶与栈底相等的时候,栈就是空栈。

//判断栈是否为空
int isEmpty(PSTACK pS)
{
    if(pS->pTop==pS->pBottom)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

3.2遍历栈

只要栈顶与栈底不相等,就遍历栈

//遍历栈
void traverseStack(PSTACK pS)
{
    if(isEmpty(pS))
    {
        printf("栈为空,不可遍历\n");
    }
    else
    {
        PNODE p=pS->pTop;
        while(p!=pS->pBottom)
        {
            printf("%d ",p->data);
            p=p->pNext;
        }
        free(p);
        pS->pTop=pS->pBottom;
    }
}

4.出栈

出栈分为三步:
1. 创建一个指针p保存pTop指针
2. 让pTop指针指向下一个元素
3. 释放掉p
如图:
这里写图片描述

//出栈
void popStack(PSTACK pS)
{
    if(isEmpty(pS))
    {
        printf("空栈,不可出栈\n");
    }
    else
    {
        //创建一个指针p保存pTop指针
        PNODE p=pS->pTop;
        //让pTop指针指向下一个元素
        pS->pTop=p->pNext;
        //释放掉p
        free(p);
    }
}

5.清空栈

1.我们直接让pTop=pBottom是否可行?

这样虽然清空了栈,但是pTop—pBottom之间的内存并没有被释放,会造成内存泄露,这样不行。

2.我们先释放pTop—pBottom之间的内存,再让pTop=pBottom。

//清空栈
void clearStack(PSTACK pS)
{
    if(isEmpty(pS))
    {
        return ;
    }
    else
    {
        PNODE p=pS->pTop;
        //1.清空pTop---pBottom之间的内存
        while(p!=pS->pBottom)
        {
            PNODE q=p->pNext;
            free(p);
            p=q;
        }
        free(p);
        //2.让pTop=pBottom
        pS->pTop=pS->pBottom;
    }
}

三.总体代码

#include <stdio.h>
#include <stdlib.h>
//链表节点的数据结构
typedef struct Node
{
    int data;
    struct Node * pNext;
}NODE,*PNODE;
//栈的数据结构
typedef struct stack
{
    PNODE pTop;
    PNODE pBottom;
}STACK,*PSTACK;
//初始化一个栈
void initStack(PSTACK pS)
{
    pS->pTop=(PNODE)malloc(sizeof(NODE));
    if(pS->pTop==NULL)
    {
        printf("栈初始化失败\n");
        exit(-1);
    }
    else
    {
        pS->pBottom=pS->pTop;
        pS->pBottom->pNext=NULL;
    }
}
//压栈
void pushStack(PSTACK pS,int val)
{
    PNODE pNew=(PNODE)malloc(sizeof(NODE));
    pNew->data=val;
    pNew->pNext=pS->pTop;
    pS->pTop=pNew;

}
//判断栈是否为空
int isEmpty(PSTACK pS)
{
    if(pS->pTop==pS->pBottom)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
//遍历栈
void traverseStack(PSTACK pS)
{
    if(isEmpty(pS))
    {
        printf("栈为空,不可遍历\n");
    }
    else
    {
        PNODE p=pS->pTop;
        while(p!=pS->pBottom)
        {
            printf("%d ",p->data);
            p=p->pNext;
        }
        free(p);
        pS->pTop=pS->pBottom;
    }
}
//出栈
void popStack(PSTACK pS)
{
    if(isEmpty(pS))
    {
        printf("空栈,不可出栈\n");
    }
    else
    {
        //创建一个指针p保存pTop指针
        PNODE p=pS->pTop;
        //让pTop指针指向下一个元素
        pS->pTop=p->pNext;
        //释放掉p
        free(p);
    }
}
//清空栈
void clearStack(PSTACK pS)
{
    if(isEmpty(pS))
    {
        return ;
    }
    else
    {
        PNODE p=pS->pTop;
        while(p!=pS->pBottom)
        {
            PNODE q=p->pNext;
            free(p);
            p=q;
        }
        free(p);
        pS->pTop=pS->pBottom;

    }
}
int main()
{
    STACK s;
    initStack(&s);
    pushStack(&s,3);
    pushStack(&s,2);
    pushStack(&s,1);
    popStack(&s);
    clearStack(&s);
    traverseStack(&s);
    return 0;
}

四.总结

栈是一种非常重要的线性结构,也是非常基本的数据结构。本文用链表的方式实现了栈。
栈在计算机领域有很多应用。
比如:函数的调用用到栈、判断回文也用到栈的知识。

所以,我们一定要掌握它!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章