您当前的位置: 首页 > 

限定性线性表(上):栈的定义及其实现

蔚1 发布时间:2018-08-14 00:43:26 ,浏览量:3

栈是一种后进先出的限定性线性表,它与递归关系紧密,在实际生产中被广泛使用,本场Chat就栈的定义及其实现做一次分享。

本场Chat内容如下:

  1. 栈的定义;
  2. 顺序栈及链栈的结构定义;
  3. 栈的七种基本操作。
限定性线性表(上):栈的定义及其实现 栈的基本定义

栈是一种限定性线性表,其特殊在于插入与删除均仅在表的一端进行,被称为栈顶(top),与之相反的一端称为栈底(bottom)。栈是由 $n≥0$ 个元素构成的,当 $n=0$ 时,称为空栈。为了描述的便利,人们将栈的插入操作,形象地称为入栈或是进栈;删除操作则是出栈或是退栈。

正是因为栈的插入与删除仅在 top 进行,因此栈也被称作后进先出(LIFO)表。

栈有三个基本特性:同一性、线性、有穷性。在链接方式上,栈被分作顺序栈与链栈。在一点上,可以类比之前讲的顺序表与链表。

当然正是因为栈的后进先出,导致了它有一个极为出名的应用:递归——在定义自身的同时,又对自身做出了调用。递归又分为线性递归与尾递归。对于尾递归的描述,在之前的《每周 Lisp:从四则运算到条件、循环、宏定义》一文中有着完备的描述。那现在着重讲一下栈是如何实现递归操作的,当然也顺带涉及线性递归。

线性递归

相较于尾递归而言,线性递归是一种繁复的操作,但用途极大。比如在解决汉塔诺、树的遍历等等问题上,均有线性递归的身影(下文均以递归指代线性递归)。

递归是将一个非常大的问题分解为几个较大问题,再分解为几个小问题,然后解决小问题,回溯解决较大问题,最后解决了最大的问题。

就比如说阶乘问题,我想计算 $ 10!$,那我就用递归的思路不停地把 10 分解成 $ 9! * 10 $,……,一直到 $ 1 * 2 * 3 * ... * 9 * 10 $,然后回溯再将各个小问题的值整合起来,就是最后 $10!$ 的答案了。

相比较于循环操作,递归确乎是繁复了。

栈是如何实现递归的呢?

栈实现递归操作,完全仰赖其后进先出的特性,图解如下。

【图一·实现图解】

顺序栈

与顺序表相同,顺序栈同样也使用一维数组作为数据存放的方式,其结构与七种基本操作如下:

Java 示例:
class MyStack{    int Maxsize=5;    int data[]=new int[Maxsize];    int top;    //新建空栈    void Stack_init(MyStack S){        S.top=0;//有些地方习惯于以top=-1为空栈标志,我习惯于用0;    }    //入栈    void Stack_push(MyStack S,int e){        if(S.top0){                System.out.println("Pop data is :"+S.data[S.top-1]);                S.top--;            }else{                System.out.println("Error!");            }        }    }    //判满    boolean Stack_Full(MyStack S){        if(S.top==S.Maxsize){            System.out.println("The Stack is Full");            return true;        }else{            System.out.println("Unfull");            return false;        }    }    //获取栈顶元素    void Stack_get_Top(MyStack S){        if(S.Stack_empty(S)==true){            System.out.println("Empty Stack");        }else{            System.out.println("The top data is "+S.data[S.top-1]);        }    }    //清空栈内元素    void Stack_clean(MyStack S){        while(S.Stack_empty(S)==false){            S.Stack_pop(S);        }        System.out.println("重置成功");    }}public class Stack{    public static void main(String []args){        MyStack S=new MyStack();        S.Stack_push(S, 1);        S.Stack_push(S, 2);        S.Stack_push(S, 3);        S.Stack_push(S, 4);        S.Stack_push(S, 5);        S.Stack_clean(S);    }}

【图二】

链栈

链栈是一种较为重要的栈结构类型,其形式和链表接近,我们来看看其结构定义与出入栈操作的实现。

C 示例:
//结构定义 typedef struct node{    int data;    struct node *next;}*LinkStack;//入栈操作 int Push(LinkStack top,int e){    node *temp;    temp=(node *)malloc(sizeof(node));    if(temp==NULL){        return(false);    }    temp->data=e;    temp->next=top->next;    top->next=temp;    return(true);}//出栈操作 int Pop(LinkStack top){    node *temp;    temp=top->next;    if(temp==NULL){        return(false);    }    top->next=temp->next;    printf("出栈元素为:%d\n",temp->data);    free(temp);    return(true);}
学习资料
  • 中国大学MOOC《数据结构·华中农业大学》
  • 《数据结构C++版·王红梅》

本文首发于GitChat,未经授权不得转载,转载需与GitChat联系。

阅读全文: http://gitbook.cn/gitchat/activity/5b5ad1b7597ecb7add3f5347

您还可以下载 CSDN 旗下精品原创内容社区 GitChat App ,阅读更多 GitChat 专享技术内容哦。

FtooAtPSkEJwnW-9xkCLqSTRpBKX

关注
打赏
1688896170
查看更多评论

蔚1

暂无认证

  • 3浏览

    0关注

    4645博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文
立即登录/注册

微信扫码登录

0.4921s