python算法(二)—栈、队列、链表、哈希

简介: python算法(二)—栈、队列、链表、哈希

数据结构:指的是相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成。比如,列表、集合和字典等都是一种数据结构。 数据结构的分类


一、栈

栈:限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。

括号匹配问题:给一个字符串,其中包括小括号、中括号、大括号,求该字符串中的括号是否匹配。例如:[(){}[]] 匹配;[]} 不匹配

class Stack:
    def __init__(self):
        self.stack = []
    def push(self, element):  # 进栈
        self.stack.append(element)
    def pop(self):  # 出栈
        return self.stack.pop()
    def get_top(self):  # 获取栈顶元素
        if len(self.stack) > 0:
            return self.stack[-1]
        else:
            return None
    def is_empty(self):
        return len(self.stack) == 0
def brace_match(s):
    match = {')': '(', ']': '[', '}': '{'}
    stack = Stack()
    for ch in s:
        if ch in {'(', '[', '{'}:
            stack.push(ch)
        else:  # ch in {')',']','}'}
            if stack.is_empty():
                return False
            elif stack.get_top() == match[ch]:
                stack.pop()
            else:  # stack.get_top() != match[ch]
                return False
    if stack.is_empty():
        return True
    else:
        return False
s1 = '[]{[]{}()}[]'
s2 = '[)]}'
print(brace_match(s1))
print(brace_match(s2))


二、队列

1、单向队列(Queue)是一个数据集合,仅允许在列表的一端进行插入(队尾),另一端进行删除(队首),按先进先出的性质(First-in ,First-out)。

单向队列的实现方式——环形队列:当队尾指针front==Maxsize+1时,再前进一个位置就自动到0。

队首指针前进1:front=(front+1)%Maxsize

队尾指针前进1:rear=(rear+1)%Maxsize

对空条件:rear=front

队满条件:(rear+1)%Maxsize=front

class Queue:
    def __init__(self,size=100):
        self.queue=[0 for _ in range(size)]
        self.size=size
        self.rear=0 #队尾指针
        self.front=0 #队首指针
    #判断队空
    def is_empty(self):
        return self.rear==self.front
    #判断队满
    def is_filled(self):
        return  (self.rear+1)%self.size==self.front
    #进队
    def push(self,element):
        if not self.is_filled():
            self.rear=(self.rear+1)%self.size
            self.queue[self.rear]=element
        else:
            raise IndexError("Queue is filled")
    #出队
    def pop(self):
        if not self.is_empty():
            self.front=(self.front+1)%self.size
            return self.queue[self.front]
        else:
            raise IndexError("Queue is empty")
q=Queue(5)
for i in range(4):
    q.push(i)
print(q.pop())


2、双向队列

两端都支持进队和出队操作

3、Python队列内置模块

from collections import deque
queue=deque()   #创建队列
queue.append(1) #队尾进队
queue.popleft() #队首出队
queue.appendleft(1)  #双向队列首进队
queue.pop() #双向队列队尾出队

如果队满则会自动出队

from collections import deque
queue=deque([1,2,3,4,5],5)
queue.append(6) 
print(queue.popleft())   # —>输出  2


三、栈和队列的应用——迷宫问题

给一个二维列表来表示迷宫(0表示通道,1表示围墙),给出算法求一条走出迷宫的路径。


1、栈——深度优先搜索(回溯法)

思路:从一个节点开始,任意找下一个能走的点(不妨默认按上-右-下-左),当找不到能走的点时,退回上一个点寻找是否有其他方向的点。用栈存储当前路径。

maze=[
    [1,1,1,1,1,1,1,1,1,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,0,0,1,1,0,0,1],
    [1,0,1,1,1,0,0,0,0,1],
    [1,0,0,0,1,0,0,0,0,1],
    [1,0,1,0,0,0,1,0,0,1],
    [1,0,1,1,1,0,1,1,0,1],
    [1,1,0,0,0,0,0,0,0,1],
    [1,1,1,1,1,1,1,1,1,1]
]
#(x,y):初始位置,dirs表示上下左右移动的位置
dirs=[
    lambda x,y:(x+1,y),
    lambda x,y:(x-1,y),
    lambda x,y:(x,y-1),
    lambda x,y:(x,y+1)
]
def maze_path(x1,y1,x2,y2):#x1,y1初始位置;x2,y2终点位置
    stack=[]
    stack.append((x1,y1))
    while len(stack)>0:
        curNode = stack[-1]  # 当前的节点位置
        #若走到了终点
        if curNode[0]==x2 and curNode[1]==y2:
            for p in stack:
                print(p)
            return True
        # (x,y)向四个方向移动
        for dir in dirs:
            nextNode=dir(curNode[0],curNode[1])
            #判断下一个节点是否能走通
            if maze[nextNode[0]][nextNode[1]]==0:
                stack.append(nextNode)
                maze[nextNode[0]][nextNode[1]]=2    #用2标记已经走过
                break
        else:
            maze[nextNode[0]][nextNode[1]]=2
            stack.pop() #若走不通,则弹出此节点,以返回上一个节点
    else:
        print("没有路")
        return False
maze_path(1,1,8,8)

2、队列——广度优先搜索

用栈做深度搜索并不能保证路线是最短的,因此用队列来进行。

思路:从一个节点开始,寻找所有接下来能继续走的点,继续不断寻找,直到找到出口。使用队列存储当前正在考虑的点。


2进队,1进队——>3进队,2出队——>4,5进队,3出队——>6,7进队,4,5出队——>……

然后,将初始位置1下标记为-1;下一个位置2是由上一个位置带入的,其下标为0;……


maze=[
    [1,1,1,1,1,1,1,1,1,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,0,0,1,1,0,0,1],
    [1,0,1,1,1,0,0,0,0,1],
    [1,0,0,0,1,0,0,0,0,1],
    [1,0,1,0,0,0,1,0,0,1],
    [1,0,1,1,1,0,1,1,0,1],
    [1,1,0,0,0,0,0,0,0,1],
    [1,1,1,1,1,1,1,1,1,1]
]
#(x,y):初始位置,dirs表示上下左右移动的位置
dirs=[
    lambda x,y:(x+1,y),
    lambda x,y:(x-1,y),
    lambda x,y:(x,y-1),
    lambda x,y:(x,y+1)
]
from collections import  deque
def print_r(path):
    curNode=path[-1]   #终点的位置
    realpath=[]     #真实路径
    while curNode[2]!=-1:
        realpath.append(curNode[0:2])
        curNode=path[curNode[2]]
    realpath.append(curNode[0:2])   #起点
    realpath.reverse()
    for node in realpath:
        print(node)
def maze_path_queue(x1,y1,x2,y2):
    queue=deque()
    queue.append((x1,y1,-1)) #将初始位置下标记作-1
    path=[]
    while len(queue)>0:
        curNode=queue.popleft() #当前节点的位置
        path.append(curNode)
        if curNode[0] == x2 and curNode[1] == y2:   #终点
            print_r(path)
            return True
        for dir in dirs:
            nextNode=dir(curNode[0],curNode[1])
            if maze[nextNode[0]][nextNode[1]]==0:
                queue.append((nextNode[0],nextNode[1],len(path)-1)) #后续可行节点进队,并记录有哪个节点带进来的
                maze[nextNode[0]][nextNode[1]]=2
    else:
        print("没有路")
        return False
maze_path_queue(1,1,8,8)


四、链表

链表是由一系列节点组成的元素集合。每个节点包含两部分,数据域item和指向下一个节点的指针next。通过节点之间的相互连接,最终串联成一个链表。

class Node:
    def __init__(self,item):
        self.item=item
        self.next=None
a=Node(1)
b=Node(2)
c=Node(3)
a.next=b
b.next=c
print('a.item:',a.item)
print('a.next.item:',a.next.item)

输出:

a.item: 1

a.next.item: 2

1、创建链表

头插法:在头节点处插入,插入的节点将成为新的头节点

尾插法:在尾节点处插入,插入的节点将成为新的尾节点

class Node:
    def __init__(self,item):
        self.item=item
        self.next=None
def creat_linklist_head(li):    #头插法
    head=Node(li[0])
    for element in li[1:]:
        node=Node(element)
        node.next=head
        head=node
    return head
def creat_linklist_tail(li):    #尾插法
    head=Node(li[0])
    tail=head
    for element in li[1:]:
        node=Node(element)
        tail.next=node
        tail=node
    return head
def print_linklist(lk):   #链表的遍历
    while lk:
        print(lk.item,end=',')
        lk=lk.next
lk1=creat_linklist_head([1,2,3])
print_linklist(lk1)  #输出3,2,1
lk2=creat_linklist_tail([1,2,3])
print_linklist(lk2) #输出1,2,3

2、节点的插入、删除

插入:4先与2相连,然后1与4相连

删除:1与2相连,再删除43、双链表每个节点有两个指针:一个指向后一个节点,另一个指向前一个节点。

class Node:
    def __init__(self,item):
        self.item=item
        self.next=None
        self.prior=None

插入:

删除:

4、复杂度分析


顺序表(列表、数组)
链表
按元素值查找 O(n) O(n)
按下标查找 O(1) O(n)
在某元素后插入 O(n) O(1)
删除某元素 O(n) O(1)


五、哈希表

哈希表是一个通过哈希函数来计算数据存储位置的数据结构,通常支持如下操作:

  • insert(key,value):插入键值对(key,value)
  • get(key):如果存在键为key的键值则返回其value,否则返回空值
  • delete(key):删除键为key的键值对

1、创建哈希表

class LinkList:  # 定义一个链表类,可支持迭代、插入、寻找、输出为字符串
    class Node:
        def __init__(self, item=None):
            self.item = item
            self.next = None
    class LinkListIterator:  # 设置成可迭代类
        def __init__(self, node):
            self.node = node
        def __next__(self):
            if self.node:
                cur_node = self.node
                self.node = cur_node.next
                return cur_node.item
            else:
                raise StopIteration
        def __iter__(self):
            return self
    def __init__(self, iterable=None):
        self.head = None
        self.tail = None
        if iterable:
            self.extend(iterable)
    def append(self, obj):
        s = LinkList.Node(obj)
        if not self.head:  # 头节点为空时
            self.head = s
            self.tail = s
        else:
            self.tail.next = s
            self.tail = s
    def extend(self, iterable):
        for obj in iterable:
            self.append(obj)
    def find(self, obj):
        for n in self:
            if n == obj:
                return True
            else:
                return False
    def __iter__(self):  # 迭代
        return self.LinkListIterator(self.head)
    def __repr__(self):  # 转换成字符串
        return "<<" + ",".join(map(str, self)) + ">>"
class HashTable:
    def __init__(self, size=101):
        self.size = size
        self.T = [LinkList() for i in range(self.size)]
    def h(self, k):
        return k % self.size
    def find(self, k):
        i = self.h(k)
        return self.T[i].find(k)
    def insert(self, k):
        i = self.h(k)
        if self.find(k):
            print("Duplicated Insert")
        else:
            self.T[i].append(k)
ht = HashTable()
ht.insert(0)
ht.insert(1)
ht.insert(3)
ht.insert(102)
ht.insert(508)
print(",".join(map(str, ht.T)))
print(ht.find(3))


目录
相关文章
|
16天前
|
机器学习/深度学习 人工智能 算法
植物病害识别系统Python+卷积神经网络算法+图像识别+人工智能项目+深度学习项目+计算机课设项目+Django网页界面
植物病害识别系统。本系统使用Python作为主要编程语言,通过收集水稻常见的四种叶片病害图片('细菌性叶枯病', '稻瘟病', '褐斑病', '稻瘟条纹病毒病')作为后面模型训练用到的数据集。然后使用TensorFlow搭建卷积神经网络算法模型,并进行多轮迭代训练,最后得到一个识别精度较高的算法模型,然后将其保存为h5格式的本地模型文件。再使用Django搭建Web网页平台操作界面,实现用户上传一张测试图片识别其名称。
66 21
植物病害识别系统Python+卷积神经网络算法+图像识别+人工智能项目+深度学习项目+计算机课设项目+Django网页界面
|
15天前
|
机器学习/深度学习 算法 TensorFlow
交通标志识别系统Python+卷积神经网络算法+深度学习人工智能+TensorFlow模型训练+计算机课设项目+Django网页界面
交通标志识别系统。本系统使用Python作为主要编程语言,在交通标志图像识别功能实现中,基于TensorFlow搭建卷积神经网络算法模型,通过对收集到的58种常见的交通标志图像作为数据集,进行迭代训练最后得到一个识别精度较高的模型文件,然后保存为本地的h5格式文件。再使用Django开发Web网页端操作界面,实现用户上传一张交通标志图片,识别其名称。
44 6
交通标志识别系统Python+卷积神经网络算法+深度学习人工智能+TensorFlow模型训练+计算机课设项目+Django网页界面
|
11天前
|
机器学习/深度学习 人工智能 算法
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
文本分类识别系统。本系统使用Python作为主要开发语言,首先收集了10种中文文本数据集("体育类", "财经类", "房产类", "家居类", "教育类", "科技类", "时尚类", "时政类", "游戏类", "娱乐类"),然后基于TensorFlow搭建CNN卷积神经网络算法模型。通过对数据集进行多轮迭代训练,最后得到一个识别精度较高的模型,并保存为本地的h5格式。然后使用Django开发Web网页端操作界面,实现用户上传一段文本识别其所属的类别。
24 1
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
|
9天前
|
大数据 UED 开发者
实战演练:利用Python的Trie树优化搜索算法,性能飙升不是梦!
在数据密集型应用中,高效搜索算法至关重要。Trie树(前缀树/字典树)通过优化字符串处理和搜索效率成为理想选择。本文通过Python实战演示Trie树构建与应用,显著提升搜索性能。Trie树利用公共前缀减少查询时间,支持快速插入、删除和搜索。以下为简单示例代码,展示如何构建及使用Trie树进行搜索与前缀匹配,适用于自动补全、拼写检查等场景,助力提升应用性能与用户体验。
27 2
|
12天前
|
算法 Python
震惊!Python 算法设计背后,时间复杂度与空间复杂度的惊天秘密大起底!
在 Python 算法设计中,理解并巧妙运用时间复杂度和空间复杂度的知识,是实现高效、优雅代码的必经之路。通过不断地实践和优化,我们能够在这两个因素之间找到最佳的平衡点,创造出性能卓越的程序。
28 4
|
13天前
|
算法 搜索推荐 开发者
别再让复杂度拖你后腿!Python 算法设计与分析实战,教你如何精准评估与优化!
在 Python 编程中,算法的性能至关重要。本文将带您深入了解算法复杂度的概念,包括时间复杂度和空间复杂度。通过具体的例子,如冒泡排序算法 (`O(n^2)` 时间复杂度,`O(1)` 空间复杂度),我们将展示如何评估算法的性能。同时,我们还会介绍如何优化算法,例如使用 Python 的内置函数 `max` 来提高查找最大值的效率,或利用哈希表将查找时间从 `O(n)` 降至 `O(1)`。此外,还将介绍使用 `timeit` 模块等工具来评估算法性能的方法。通过不断实践,您将能更高效地优化 Python 程序。
30 4
|
11天前
|
算法 程序员 Python
程序员必看!Python复杂度分析全攻略,让你的算法设计既快又省内存!
在编程领域,Python以简洁的语法和强大的库支持成为众多程序员的首选语言。然而,性能优化仍是挑战。本文将带你深入了解Python算法的复杂度分析,从时间与空间复杂度入手,分享四大最佳实践:选择合适算法、优化实现、利用Python特性减少空间消耗及定期评估调整,助你写出高效且节省内存的代码,轻松应对各种编程挑战。
22 1
|
12天前
|
算法 计算机视觉 Python
Python并查集大揭秘:让你在算法界呼风唤雨,秒杀一切复杂场景!
在编程与算法的广袤天地中,总有一些工具如同神兵利器,能够助你一臂之力,在复杂的问题前游刃有余。今天,我们就来深入探讨这样一件神器——Python并查集(Union-Find),看看它是如何让你在算法界呼风唤雨,轻松应对各种复杂场景的。
28 2
|
11天前
|
机器学习/深度学习 人工智能 算法
【果蔬识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
【果蔬识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台。果蔬识别系统,本系统使用Python作为主要开发语言,通过收集了12种常见的水果和蔬菜('土豆', '圣女果', '大白菜', '大葱', '梨', '胡萝卜', '芒果', '苹果', '西红柿', '韭菜', '香蕉', '黄瓜'),然后基于TensorFlow库搭建CNN卷积神经网络算法模型,然后对数据集进行训练,最后得到一个识别精度较高的算法模型,然后将其保存为h5格式的本地文件方便后期调用。再使用Django框架搭建Web网页平台操作界面,实现用户上传一张果蔬图片识别其名称。
31 0
【果蔬识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
|
15天前
|
缓存 算法 数据处理
时间&空间复杂度,Python 算法的双重考验!如何优雅地平衡两者,打造极致性能?
在Python算法中,时间与空间复杂度的平衡至关重要。时间复杂度反映算法执行时间随输入规模的变化趋势,空间复杂度则关注额外存储空间的需求。优秀的算法需兼顾两者,如线性搜索时间复杂度为O(n),空间复杂度为O(1);二分查找在时间效率上显著提升至O(log n),空间复杂度保持为O(1);动态规划通过牺牲O(n)空间换取O(n)时间内的高效计算。实际应用中,需根据具体需求权衡,如实时数据处理重视时间效率,而嵌入式系统更关注空间节约。通过不断优化,我们能在Python中找到最佳平衡点,实现高性能程序。
37 3
下一篇
无影云桌面