C语言中数据结构——栈

博主主页:@ᰔᩚ. 一怀明月ꦿ 

❤️‍专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++,数据结构

座右铭:“不要等到什么都没有了,才下定决心去做”

大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点

目录

栈 

栈的概念

顺序表和链表的优缺点

栈结构体的定义

栈的初始化

栈的销毁

入栈

出栈

栈顶元素

判断的栈是否为空

栈元素个数

栈的源码

main文件

test.h文件

test.h文件


栈 

栈的概念

顺序表和链表的优缺点

顺序表的缺点:

1.前面部分插入删除数据,效率是O(N),需要挪动数据。(物理空间是连续的)

2.空间不够,需要扩容。a.扩容是需要付出代价的,b.一般还会伴随空间浪费

顺序表的优点:

1.尾插尾删效率比较高

2.下标的随机访问

3.cpu高速缓存命中率较高

链表(带头双向循环链表)优点:

1.任意位置插入删除O(1)

2.按需申请释放空间

链表缺点:

不支持下标的随机访问

cpu高速缓存命中率较低

                

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底栈中数据元素遵守后进先出(LIFO)的原则。

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶

出栈:栈的删除操作叫做出栈,出数据也在栈顶

栈就是在线性表的基础上加以限制(遵循后进先出的原则)

例如:

入栈:1 2 3 4

出栈:4 3 2 1(入完4个数据在出数据)

            1 2 3 4(入一个数据,出一个数据)

            3 2 4 1(先入1 2 3,再出3 2,再入4,出 4 1)

...

注意:  3 1 4 2这种出栈的顺序是不可能的

实现栈有两种形式:

1.数组栈(顺序表)(尾做栈顶)

2.链表栈(链表)(用头做栈顶)

本文使用的就是第一种,用顺序表完成的栈

栈结构体的定义

1.a动态存储数据的数组 2.top栈有效元素的个数 3.capacity栈的容量

typedef int STDataType;
typedef struct Stack
{
    STDataType* a;
    int top;
    int capacity;
}ST;

栈的初始化

栈的初始化,这里是将栈元素的有效个数设置为0(pst->top=0),你也可以把它设置为-1,根据自己的要求设计

void STInit(ST* pst)
{
    assert(pst);
    pst->a=NULL;
//    pst->top=-1;//指向栈顶数据
    pst->top=0;//指向栈顶数据的下一个位置
    pst->capacity=0;
}

栈的销毁

由于是顺序表栈,只需要free头指针就行,将结构体元素全部置空

void STDestroy(ST* pst)
{
    assert(pst);
    free(pst->a);
    pst->a=NULL;
    pst->top=pst->capacity=0;
}

入栈

栈(顺序表)采用的是尾插法来完成入栈

void STPush(ST* pst,STDataType x)
{
    assert(pst);
    if(pst->capacity==pst->top)
    {
        //如果栈容量为空则,则开辟四个空间,否则新开辟的空间是原来空间的两倍
        int newCapacity=pst->capacity==0?4:pst->capacity*2;
        STDataType* temp=(STDataType *)realloc(pst->a,newCapacity*sizeof(STDataType));
        if(temp==NULL)
        {
            perror("realloc fail");
            return ;
        }
        pst->a=temp;
        pst->capacity=newCapacity;
    }
    pst->a[pst->top]=x;
    pst->top++;
}

出栈

出栈就是将元素移除栈,这里采用了顺序表的尾删,直接将栈内有效个数(pst->top)减一

void STPop(ST* pst)
{
    assert(pst);
    assert(!STEmpty(pst));
    pst->top--;
}

栈顶元素

返回栈顶的元素,这里注意一下,top是有效个数是从1开始记录的,但是顺序表的下表从0开始记录,所以我们这里pst->top-1

STDataType STTop(ST* pst)
{
    assert(pst);
    assert(!STEmpty(pst));
    return pst->a[pst->top-1];
}

判断的栈是否为空

判断栈内元素是否为空,如果为空返回true,否则返回false

bool STEmpty(ST* pst)
{
    assert(pst);
    return pst->top==0;
}

栈元素个数

判断栈元素的有效个数,并返回

int STSize(ST* pst)
{
    assert(pst);
    return pst->top;
}

栈的源码

main文件

#include "test.h"
void test1(void)
{
    ST s1;
    STInit(&s1);
    STPush(&s1, 1);
    STPush(&s1, 2);
    STPush(&s1, 3);
    STPush(&s1, 4);
    printf("total:%d\n",STSize(&s1));
    while(!STEmpty(&s1))
    {
        printf("%d ",STTop(&s1));
        STPop(&s1);
    }
}
int main()
{
    test1();
    return 0;
}
//结果:
//total:4
//4 3 2 1

test.h文件

#ifndef test_h
#define test_h

#include 
#include
#include
#include
#endif /* test_h */

typedef int STDataType;
typedef struct Stack
{
    STDataType* a;
    int top;
    int capacity;
}ST;

//栈的初始化
void STInit(ST* pst);
//栈的销毁
void STDestroy(ST* pst);
//入栈
void STPush(ST* pst,STDataType x);
//出栈
void STPop(ST* pst);
//栈顶元素
STDataType STTop(ST* pst);
//判断的栈是否为空
bool STEmpty(ST* pst);
//栈元素个数
int STSize(ST* pst);

test.h文件

#include "test.h"
//栈的初始化,这里是将栈元素的有效个数设置为0(pst->top=0),你也可以把它设置为-1,根据自己的要求设计
void STInit(ST* pst)
{
    assert(pst);
    pst->a=NULL;
//    pst->top=-1;//指向栈顶数据
    pst->top=0;//指向栈顶数据的下一个位置
    pst->capacity=0;
}
//由于是顺序表栈,只需要free头指针就行,将结构体元素全部置空
void STDestroy(ST* pst)
{
    assert(pst);
    free(pst->a);
    pst->a=NULL;
    pst->top=pst->capacity=0;
}
//栈(顺序表)采用的是尾插法来完成入栈
void STPush(ST* pst,STDataType x)
{
    assert(pst);
    if(pst->capacity==pst->top)
    {
        //如果栈容量为空则,则开辟四个空间,否则新开辟的空间是原来空间的两倍
        int newCapacity=pst->capacity==0?4:pst->capacity*2;
        STDataType* temp=(STDataType *)realloc(pst->a,newCapacity*sizeof(STDataType));
        if(temp==NULL)
        {
            perror("realloc fail");
            return ;
        }
        pst->a=temp;
        pst->capacity=newCapacity;
    }
    pst->a[pst->top]=x;
    pst->top++;
}
//出栈就是将元素移除栈,这里采用了顺序表的尾删,直接将栈内有效个数(pst->top)减一
void STPop(ST* pst)
{
    assert(pst);
    assert(!STEmpty(pst));
    pst->top--;
}
//返回栈顶的元素,这里注意一下,top是有效个数是从1开始记录的,但是顺序表的下表从0开始记录,所以我们这里pst->top-1
STDataType STTop(ST* pst)
{
    assert(pst);
    assert(!STEmpty(pst));
    return pst->a[pst->top-1];
}
//判断栈内元素是否为空,如果为空返回true,否则返回false
bool STEmpty(ST* pst)
{
    assert(pst);
    return pst->top==0;
}
//判断栈元素的有效个数,并返回
int STSize(ST* pst)
{
    assert(pst);
    return pst->top;
}

  如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家!

你可能感兴趣的:(数据结构,数据结构)