数据结构-栈

栈的定义

栈是一种特殊的线性表,仅允许在表的一端进行插入和删除运算。这一端被称为栈顶(top),相对地,把另一端称为栈底(bottom)。向一个栈插入新元素又称作进栈、入栈或压栈(push),它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈(pop),它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。所以栈具有“后入先出”的特点(LIFO)。

栈的存储结构

顺序存储于链式存储都能实现一个栈,其中顺序存储的形式大概是这样:

一般的,把数组的第一个位置[0]作为栈底,再单独定义一个变量指示栈顶:

/* 顺序栈结构 */
typedef int SElemType; 
typedef struct
{
        SElemType data[MAXSIZE];
        int top; /* 用于栈顶指针 */
}SqStack;

在栈的链式结构实现中,一般把链表的头指针做为栈顶,按照先后顺序来看的,这种定义与数组正好是反过来的,这是由于在顺序结构中,查找是非常方便的,插入和移动不方便。但是链式结构只知道头指针,查找不方便,但是插入方便,而对于栈而言,我们需要知道栈顶的位置,所以就干脆把链表头指针作为栈顶吧,同时由于插入方便,每次在链的开头插入一个结点很容易。

那么栈的链式存储的形式大概是这样:

typedef int SElemType; 
/* 链栈结构 */
typedef struct StackNode
{
        SElemType data;
        struct StackNode *next;
}StackNode,*LinkStackPtr;

栈的常用操作

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20 
typedef int Status; 
typedef int SElemType; 
Status visit(SElemType c)
{
        printf("%d ",c);
        return OK;
}

顺序栈:

/*  构造一个空栈S */
Status InitStack(SqStack *S)
{ 
    /* S.data=(SElemType *)malloc(MAXSIZE*sizeof(SElemType)); */
    S->top=-1;
    return OK;
}

/* 把S置为空栈 */
Status ClearStack(SqStack *S)
{ 
    S->top=-1;
    return OK;
}

/* 若栈S为空栈,则返回TRUE,否则返回FALSE */
Status StackEmpty(SqStack S)
{ 
    if (S.top==-1)
        return TRUE;
    else
        return FALSE;
}

/* 返回S的元素个数,即栈的长度 */
int StackLength(SqStack S)
{ 
    return S.top+1;
}

/* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
Status GetTop(SqStack S,SElemType *e)
{
    if (S.top==-1)
        return ERROR;
    else
        *e=S.data[S.top];
    return OK;
}

/* 插入元素e为新的栈顶元素 */
Status Push(SqStack *S,SElemType e)
{
    if(S->top == MAXSIZE -1) /* 栈满 */
    {
        return ERROR;
    }
    S->top++;               /* 栈顶指针增加一 */
    S->data[S->top]=e;  /* 将新插入元素赋值给栈顶空间 */
    return OK;
}

/* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
Status Pop(SqStack *S,SElemType *e)
{ 
    if(S->top==-1)
        return ERROR;
    *e=S->data[S->top]; /* 将要删除的栈顶元素赋值给e */
    S->top--;               /* 栈顶指针减一 */
    return OK;
}

/* 从栈底到栈顶依次对栈中每个元素显示 */
Status StackTraverse(SqStack S)
{
    int i;
    i=0;
    while(i<=S.top)
    {
        visit(S.data[i++]);
    }
    printf("\n");
    return OK;
}

链栈:

/*  构造一个空栈S */
Status InitStack(LinkStack *S)
{ 
        S->top = (LinkStackPtr)malloc(sizeof(StackNode));
        if(!S->top)
                return ERROR;
        S->top=NULL;
        S->count=0;
        return OK;
}

/* 把S置为空栈 */
Status ClearStack(LinkStack *S)
{ 
        LinkStackPtr p,q;
        p=S->top;
        while(p)
        {  
                q=p;
                p=p->next;
                free(q);
        } 
        S->count=0;
        return OK;
}

/* 若栈S为空栈,则返回TRUE,否则返回FALSE */
Status StackEmpty(LinkStack S)
{ 
        if (S.count==0)
                return TRUE;
        else
                return FALSE;
}

/* 返回S的元素个数,即栈的长度 */
int StackLength(LinkStack S)
{ 
        return S.count;
}

/* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
Status GetTop(LinkStack S,SElemType *e)
{
        if (S.top==NULL)
                return ERROR;
        else
                *e=S.top->data;
        return OK;
}

/* 插入元素e为新的栈顶元素 */
Status Push(LinkStack *S,SElemType e)
{
        LinkStackPtr s=(LinkStackPtr)malloc(sizeof(StackNode)); 
        s->data=e; 
        s->next=S->top; /* 把当前的栈顶元素赋值给新结点的直接后继,见图中① */
        S->top=s;         /* 将新的结点s赋值给栈顶指针,见图中② */
        S->count++;
        return OK;
}

/* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
Status Pop(LinkStack *S,SElemType *e)
{ 
        LinkStackPtr p;
        if(StackEmpty(*S))
                return ERROR;
        *e=S->top->data;
        p=S->top;                   /* 将栈顶结点赋值给p,见图中③ */
        S->top=S->top->next;    /* 使得栈顶指针下移一位,指向后一结点,见图中④ */
        free(p);                    /* 释放结点p */        
        S->count--;
        return OK;
}
/* 从栈底到栈顶依次对栈中每个元素显示 */
Status StackTraverse(LinkStack S)
{
        LinkStackPtr p;
        p=S.top;
        while(p)
        {
                 visit(p->data);
                 p=p->next;
        }
        printf("\n");
        return OK;
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏张俊红

数据结构-栈和队列

我们把类似于弹夹那种先进后出的数据结构称为栈,栈是限定仅在表尾进行插入和删除操作的线性表,我们把允许插入和删除的一端称为栈顶,另一端称为栈底,不含任何数据元素的...

1042
来自专栏高性能服务器开发

(四)sds字符串

今天分析的是Redis源码中的字符串操作类的代码实现。有了上几次的分析经验,渐渐觉得我得换一种分析的方法,如果每个API都进行代码分析,有些功能性的重复,导致分...

35710
来自专栏武培轩的专栏

Leetcode#500. Keyboard Row(键盘行)

给定一个单词列表,只返回可以使用在键盘同一行的字母打印出来的单词。键盘如下图所示。

1502
来自专栏鸿的学习笔记

python的装饰器和闭包

因为在编译时,python会认为b是局部变量,这是python的一个设计选择,为了避免变量的污染,想一想。如果某人在函数内部改动了变量,你没有办法看到这个函数,

811
来自专栏Java Edge

"聊胜于无",浅析Java中的原子操作Java的指针Unsafe类i++不是线程安全的1 原子更新基本类型类2 原子更新数组3 AtomicReference(原子更新引用)4 原子更新字段Atomi

4936
来自专栏DHUtoBUAA

《剑指Offer》附加题_用两个队列实现一个栈_C++版

  在《剑指Offer》中,在栈和队列习题中,作者留下来一道题目供读者自己实现,即“用两个队列实现一个栈”。   在计算机数据结构中,栈的特点是后进先出,即最后...

2805
来自专栏文武兼修ing——机器学习与IC设计

栈与栈的实现栈栈的基本操作栈的实现

栈 栈是一种基础的数据结构,只从一端读写数据。基本特点就”后进先出“,例如顺序入栈1,2,3,4,5,再顺序出栈是5,4,3,2,1 栈的基本操作 栈的基本操作...

2885
来自专栏猿人谷

C++ STL算法系列5---equal() , mismatch()

equal和mismatch算法的功能是比较容器中的两个区间内的元素。这两个算法各有3个参数first1,last1和first2.如果对 于区间[first1...

2218
来自专栏屈定‘s Blog

(转)Java--栈与队列

Java中栈与队列相比集合来说不是很常用的数据结构,因此经常被忽略.个人觉得还是有必要掌握下,以备不时之需. Java中实际上提供了java.util.Stac...

2513
来自专栏Bingo的深度学习杂货店

Q28 Implement strStr()

Implement strStr(). Return the index of the first occurrence of needle in haysta...

31810

扫码关注云+社区