【数据结构】这一栈,我们必定拿下

😉博客主页倒霉沙拉🥗
💘欢迎关注👍评论🏆关注⭐️
🏃一起坚持,一起成长!
✏️如果文章中有错误或者大家有更好的想法,可以评论指出,谢谢!


在这里插入图片描述


0.前方有言

学习一个数据结构的顺序:
逻辑结构——存储结构——运算与操作
按照这样的顺序在大脑里构建思维导图会加深记忆哈!

1.栈的基本概念

1.1什么是栈?

栈是一种只能在同一端进行插入或删除操作的线性表(也称线性多项集)。
从概念中我们不难看出,栈其实就是一种特殊的线性表!
那么它特殊在哪里以至于我们可以单独拿出来作为一种新的数据结构来讨论呢?

1.2栈何以立于不败之地?

下面我们用生活中的例子来进入栈:
在这里插入图片描述

上图是一些书堆成的栈,这样堆起来的话只有最上面的Python会露出封面,当我们想要拿到其他的书的时候,我们就需要一本一本移除压在其上面的书,这样生活中不起眼的一些行为便包含着栈的主要特点,即“后进先出”或者“先进后出”,也就是说后进栈的元素先出栈,栈也因此被称为后进先出表

当然,除了这个最重要的特点之外,栈还有一些专业领域需要我们去了解:

栈中允许进行插入、删除操作的一端称为栈顶,那么另一端就称为栈底了;
栈中没有数据元素时称为空栈(此时披着线性表的外衣,也就难以分辨是栈还是它大哥了);
栈的插入操作通常称为进栈、入栈或者是推入
栈的删除操作通常称为退栈、出栈或者是弹出

在以上都了解之后,那么对于栈来说,我们算是入门了,但是想要在栈的道路上继续耕耘,我们任重道远,还是需要继续往下看的;

2.栈的存储结构与基本运算

既然我们谈到栈是一种特殊的线性表,那么谈到栈的存储结构的时候,我们是不是就会联想到线性表的存储结构呢?
如果可以,还是需要继续看的;

2.1栈的顺序存储结构

在采用顺序存储结构时,用列表来存放栈中元素的栈就是顺序栈
顺序栈生命周期内的一些操作
由图我们可以总结出来顺序栈的四特点:
1)栈空条件:len(data)==0;
2)栈满条件:在Python中,列表是可以动态扩展的,所以我们不需要考虑栈满;
3)进栈操作:从上图可以看到使用了push( )的操作将元素添加在栈顶处;
4)出栈操作:使用了pop( )方法删除栈顶元素并返回该元素(有返回值的,这个要注意!)。

2.2顺序栈为我所用

学习的目的是为了应用,那么怎样才能让顺序栈为我们所用呢?
栈的一些操作
上面是对栈的一些操作的汇总,接下来我们来详细看一下栈的操作的具体实现吧(附代码):

1.判断栈是否为空:

def isEmpty(self):
	if len(self.data)==0:	#判断列表的长度是否为0
		return True
	return False

2.进栈:

def push(self,e):
	self.data.append(e)

采用了列表的append方法将元素添加在栈顶。

3.出栈:

def pop(self):
	return self.data.pop()

4.取栈顶元素:

def peek(self):
	return self.data[-1]

2.3栈的链式存储结构

采用链式存储的栈称为链栈链栈的存储结构
类比顺序栈的四特点,我们可以得到链栈的:
1)栈空条件:head.next==None
2)栈满条件:不需要考虑栈满上溢出,这同样是链栈的一个优点;
3)进栈操作:使用push( )方法;
4)出栈操作:使用pop( )方法。

2.4怎样掌控链栈?

工欲善其事必先利其器;
想要熟练使用链栈,我们得先了解链栈的操作:
别跑神,看我操作!

1.判断栈是否为空:

def isEmpty(self):
	if self.head.next==None:
		return True
	return False

2.进栈:

def push(self,e):
	p=LinkNode(e)
	p.next=self.head.next
	self.head.next=p

3.出栈:

def pop(self):
	p=self.head.next
	self.head.next=p.next
	return p.data

4.取栈顶元素:

def peek(self):
	return self.head.next.data

3.栈的一些综合应用

1.回溯算法求解迷宫问题

一讲到迷宫,相信大家小时候包括现在都可能玩过,包括我们现在在最强大脑中见到过的蜂巢迷宫等;
蜂巢迷宫(来自百度)

其实迷宫也是有很长的历史了,迷宫最初是在克里特岛的克诺索斯宫出现,这里是米诺斯文明的中心。克诺索斯宫是政治与仪式的中心,以房间、起居空间、室内外的精美壁画以及具有高度装饰性的陶器组成的迷宫闻名。

回到我们今天的主题,借助栈,采用回溯算法求解迷宫问题;

回溯算法是什么呢?

拿我们自己玩迷宫的经历,当我们走到不通的路时,我们会返回重新选择另一个路口,回溯算法的设计便是出自于这样的考虑,计算机在求解迷宫问题时,采用的是遍历方法,通过对迷宫的各个路口遍历,遇到不通的路时,就像栈的操作一样,把走过的给移除,重新选择另一个路口,每次遍历都将路线加入在栈中,最终从入口到出口便会形成一个路径栈;这便是我们这个问题的设计思路。

我们该怎样取表示迷宫呢?

需要求解路线的迷宫图
从图中我们可以看出来,迷宫的构成是由一个个方块构成的,这样的我们我们便可以建立一个二维列表,用0表示白块(即通路),用1表示黑块(即围墙),这样的话因为入口和出口都是确定的,我们便可以将其看作围墙,由此可以将迷宫表示成:

 maze = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
         [1, 0, 0, 0, 0, 1, 0, 1, 1, 1],
         [1, 0, 1, 1, 0, 1, 0, 0, 0, 1],
         [1, 0, 1, 1, 0, 1, 1, 1, 0, 1],
         [1, 0, 1, 1, 0, 0, 0, 0, 0, 1],
         [1, 0, 1, 1, 0, 1, 1, 1, 1, 1],
         [1, 0, 1, 1, 0, 0, 0, 0, 0, 1],
         [1, 0, 1, 1, 1, 1, 1, 1, 1, 1],
         [1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
         [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]

怎样判断所走的方向?

当我们解决了上面的问题之后,我们就要开始考虑在任何一个位置的时候我们该选择哪一个方向走呢?其实要考虑这个就已经涉及到了路线的设计了,但是我们要清楚的是只有标记为0的位置才是可以走的,那我们在上下左右四个相邻方块中我们该怎样选择呢?这是我们第二步需要解决的问题;这样的话就要涉及到一个偏移量的问题,我们首先需要对方块进行编号;
按照左上角为0,横着0~9为x;纵向0-9为y;按照顺时针方向递增编号,这样我们可以得到x,y的偏移量为:

dx=[-1,0,1,0]
dy=[0,1,0,-1]

怎样走出迷宫?

在前面的两个问题都搞明白之后,我们就要开始设计走出迷宫的算法啦;
在正式设计之前,我们需要先建立一个栈类与一个方位类;

class SqStack:              #建立的栈类
    def __init__(self):
        self.data=[]

    def empty(self):
        if len(self.data)==0:
            return True
        return False

    def push(self,e):
        self.data.append(e)

    def pop(self):
        assert not self.empty()
        return self.data.pop()

    def gettop(self):
        assert not self.empty()
        return self.data[-1]


class Box:
    def __init__(self,i1,j1,di1):
        self.i=i1
        self.j=j1
        self.di=di1

这些类的建立方法,在上面的文章中都有涉及到;
之后就到最重要的部分了,我们需要从入口到出口(均以给定),我们就需要将当前方块的位置坐标放入栈中,依次遍历四个方向找到正确路径,如果走至错误路口,便根据栈的特点移除栈顶元素探索另一条路径;
代码如下:

def mazepath(xi,yi,xe,ye):
    global maze             #将迷宫数组定为全局变量
    maze = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 0, 0, 0, 0, 1, 0, 1, 1, 1],
            [1, 0, 1, 1, 0, 1, 0, 0, 0, 1],
            [1, 0, 1, 1, 0, 1, 1, 1, 0, 1],
            [1, 0, 1, 1, 0, 0, 0, 0, 0, 1],
            [1, 0, 1, 1, 0, 1, 1, 1, 1, 1],
            [1, 0, 1, 1, 0, 0, 0, 0, 0, 1],
            [1, 0, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
    st=SqStack()            #定义一个顺序栈
    dx=[-1,0,1,0]
    dy=[0,1,0,-1]
    e=Box(xi,yi,-1)         #建立入口方块对象
    st.push(e)              #入口方块进栈
    maze[xi][yi]=-1         #将进栈的方块置为-1,为了避免来回找相邻方块
    while not st.empty():
        b=st.gettop()       #取栈顶方块,称为当前方块
        if b.i==xe and b.j==ye:
            for k in range(len(st.data)):
                print("["+str(st.data[k].i)+','+str(st.data[k].j)+"]""\n",end=' ')
            return True
        find=False
        di=b.di
        while di<3 and find==False:
            di+=1
            i,j=b.i+dx[di],b.j+dy[di]
            if maze[i][j]==0:
                find=True
        if find:
            b.di=di
            b1=Box(i,j,-1)
            st.push(b1)
            maze[i][j]=-1
        else:
            maze[b.i][b.j]=0
            st.pop()
    return False

xi,yi=1,6
xe,ye=8,8
print("迷宫路径为:",end=' ')
if not mazepath(xi,yi,xe,ye):
    print("该迷宫无解")

最后将上述代码拼接在一起,便可以得到求解的路径了!
迷宫路径

4.写在最后

到栈啦!
一个课间的时间便可以掌握了数据结构栈的全部基础,有时间的话还可以看一看迷宫的题目,考虑到文章篇幅与冗杂度问题,文章中没有放入过多眼花缭乱的图片,题目也只放入了一道综合应用的;但是呢,此非终版,我也会根据不同阶段的理解对文章进行改善,也会陆陆续续添加入一些新的有趣的题目!

对你有用的话,点个赞再走吧!
有建议的话,可以评论区轰炸我!

  • 8
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
爆肝三万字的《数据仓库体系》是一本深入且详尽的学习资料,涵盖了数据仓库的方方面面。通过阅读和学习这本书,我对数据仓库的概念、架构和实践有了更深入的了解,同时也掌握了相关的技术和工具。 通过研读这本书,我掌握了数据仓库的设计原则和方法,了解了ETL(抽取、转换、加载)过程,以及各种数据模型和数据仓库架构。通过理论学习和实践操作,我能够进行数据仓库的需求分析、逻辑设计、物理设计和实施,可以从原始数据提取、清洗和转化出有价值的数据,形成信息化的决策支持。 除了理论知识,这本书还介绍了各种数据仓库工具和平台,例如ETL工具、数据库管理系统等,我能够熟练地使用这些工具进行数据仓库的建设和管理。我还了解到了数据挖掘和商业智能的相关知识,这些都是数据仓库体系的重要组成部分。 在阅读这本书的过程,我不仅拓宽了自己的专业知识,也培养了自学能力和解决问题的能力。通过实践项目,我能够从实际需求分析和理解问题,并提供解决方案。同时,我也锻炼了自己的团队合作和沟通能力,能够与他人共同完成项目,并达成共同目标。 因此,通过爆肝三万字的阅读与学习,《数据仓库体系》帮助我掌握了数据仓库的核心知识和技能,轻松拿下字节的offer。我相信在未来的工作,我能够运用所学的知识和技能,在数据仓库领域做出卓越的成绩。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MUSE_X

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值