IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【数据结构】这一栈,我们必定拿下 -> 正文阅读

[数据结构与算法]【数据结构】这一栈,我们必定拿下

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


在这里插入图片描述


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.写在最后

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

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

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-12-19 18:27:38  更:2021-12-19 18:27:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 16:36:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码