栈(stack) C语言实现 详解

栈是数据结构中较为简单的结构体,是一种操作收到限制的线性表.但简单不代表没用,毕竟数组还贼简单呢.谁敢说数组没用?

栈的理论

  • 栈是一个先进后出的结构,类似于堆盘子,先放到地上的盘子最后被取走(默认只能取走一个盘子)
  • 栈其实就是操作受限的线性表,只有一个口,每一次操作时,这个口可以当出口也可以当入口.
  • 例如:水桶,注入水时,水桶的头当做入口,倒水时,水桶的头当做出口

栈的图解.

在图解之前,先举一个例子,让大家记住栈:
栈其实就是吃了一顿饭,然后吐出来.

  • 1. 这是一个空栈,只有上面是入口和出口
    一个空栈
  • 放入一个元素a
    放入一个元素a
  • 放入一个元素b
  • 放入一个元素c
    分别放入一个元素b和c
  • 取出一个元素,由栈只有一个口的特点可以知道取出了C
    这里写图片描述
  • 再次放入一个元素d
    放入元素d

由图可以得到:无论是入,还是出,都只有一个口,一个口担当两个作用.

栈的可用操作

根据理论环节,可以轻易的看出:栈的基本操作只有两个:

  • 入栈
  • 出栈
    但是如果栈已经放满了,就像水桶装满了水一样,不能再放水了,即不能再进行入栈操作,所以要在每次入栈前判断栈满的情况.
    同理,出栈之前,栈中必须有数据,不然就出现要么空指针,要么野指针.都不是我们想要的结果,所以出栈前要判断栈空,.
    所有一个栈一共有四个功能:

-入栈(英文名:push)
-判(栈)满(isFull)
-出栈(pop)
-判(栈)空(isEmpty)

栈的C语言定义(结构体)

开篇就说了栈是操作收到限制的线性表,而众所周知的线性表主要有:
1.顺序存储的数组,
优点: 节省空间, 操作简单,学习成本较低,易于理解.
缺点: 栈的大小一开始就声明’死’了,不利于使用.
2.非顺序存储的链表.
优缺点:与数组栈正好相反.

  • 两种栈各有好处,争论是愚蠢的,学习是学不完的,所以赶快开始coding吧

数组栈

  • 数组栈,顾名思义,就是基于数组的栈,也是说把一个数组的强大的下标功能阉割掉,并且只能从一头进入(数组头明显更为方便)
    所以结构体为:
    (为了方便学习,存储类型统一使用int,但是我们一般更习惯在头文件下面给int 起一个别名,原因很简单:这样就这样实现简单的多态,需要将int类型栈改成char类型栈时,只需要改定义的别名中的类型即可)
typedef struct
{
    int Data[MaxSize];   // 存储元素的数组
    intTop;       //栈顶指针
}SeqStack;
  • 栈的四个基本操作定义
//return 0 为false,1为true(下同)
int Push(SeqStack &L)
{
    if(L.Top == 0)
    {
        return 0;
    }
    printf("%d ",L.Data[--L.Top]);
    return 1;
}
int Pop(SeqStack &L, int e)
{
    if(L.Top==MaxSize -1)
    {
        return 0;
    }
    L.Data[L.Top++] = e;
    return 1;
}
//判断栈s是否为空
int isEmpty(SeqStack s)
{
    if(s.Top != 0)
    {
        return 1;
    }
    return 0;
}
Status isFull(SeqStack s)
{
    if(s.Top != MaxSize -1)//之前的定义数组的最大值的下标
    {
        return 1;
    }
    return 0;
}

链表栈

结构体

typedef struct LNode
{
    ElemType data;
    struct LNode * next;
} LNode,*LinkList;

两大功能(链表无需判满,判空也简单,不再单独实现)

Status Push(LinkList L)
{
    if(L->next == NULL)
    {
        return 0;
    }
    LinkList tem = L->next;
    printf("%d ",tem->data);
    L->next = tem->next;
    free(tem);
    return 1;
}
Status Pop(LinkList L, ElemType e)
{
    LinkList newNode = (LinkList) malloc(sizeof(LinkList));
    newNode->data = e;
    newNode->next = L->next;
    L->next = newNode;
    return 1;
}

最后写几个简单的作业(我们老师留给我们的)以及我的代码

//1、本题要求实现顺序栈,写出Push 、Pop、StackEmpty函数的实现,并用一个简单的main函数测试。

//已有类型定义
typedef struct
{
    ElementType Data[MaxSize];   // 存储元素的数组
    Position Top;       //栈顶指针
}SeqStack;

//函数接口定义:
Status Push(SeqStack &L, ElemType e);
Status Pop(SeqStack &L, ElemType &e);
Status StackEmpty(SeqStack s);  //判断栈s是否为空
//其中 L 和 e 都是用户传入的参数。 L 是带头结点的头指针; e 是数据元素。
/**
* 3、进制转换。
* 输入一个十进制正整数n和一个目标进制R(1<R<10),将n转换为R进制。要求不使用递归或数组,而使用第1题或第2题中定义的栈来实现。 
*/ 

代码:

#include <stdio.h>
#include <stdlib.h>
#define MaxSize 100
typedef int Status;
typedef int ElemType;
typedef int Position;
//1、本题要求实现顺序栈,写出Push 、Pop、StackEmpty函数的实现,并用一个简单的main函数测试。
//已有类型定义
typedef struct
{
    ElemType Data[MaxSize];   // 存储元素的数组
    Position Top;       //栈顶指针
} SeqStack;

//函数接口定义:
Status Push(SeqStack &L);
Status Pop(SeqStack &L, ElemType e);
Status StackEmpty(SeqStack s);  //判断栈s是否为空
Status prinStack(SeqStack &L);
Status convNum(int n, int R);
Status pipei();
void work1();
//其中 L 和 e 都是用户传入的参数。 L 是带头结点的头指针; e 是数据元素。
int main()
{
    //work1();//第一题
    //convNum(8,2);//进制转化
    pipei();
    return 0;
}
Status prinStack(SeqStack &L)
{
    while (StackEmpty(L))
    {
        Push(L);
    }
    return 1;
}
void work1()
{
    SeqStack L;
    L.Top = 0;
    Pop(L, 1);
    Pop(L, 2);
    Pop(L, 3);
    prinStack(L);
}
Status Push(SeqStack &L)
{
    if(L.Top == 0)
    {
        return 0;
    }
    printf("%d ",L.Data[--L.Top]);
    return 1;
}
Status Pop(SeqStack &L, ElemType e)
{
    if(L.Top==MaxSize -1)
    {
        return 0;
    }
    L.Data[L.Top++] = e;
    return 1;
}
//判断栈s是否为空
Status StackEmpty(SeqStack s)
{
    if(s.Top != 0)
    {
        return 1;
    }
    return 0;
}
//3、进制转换。
//输入一个十进制正整数n和一个目标进制R(1<R<10),将n转换为R进制。要求不使用递归或数组,而使用第1题或第2题中定义的栈来实现。
Status convNum(int n, int R)
{
    //声明栈
    SeqStack L;
    L.Top = 0;
    while (n!=0)
    {
        //将每次产生的余数防入栈低
        Pop(L, n%R);
        n/=R;
    }
    prinStack(L);
    return 1;
}

猜你喜欢

转载自blog.csdn.net/m0_37961948/article/details/80245008