• Python数据结构


    一.列表:在其他语言中成为数组,是一种基本的数据结构类型

       1.列表中的元素如何存储

       2.列表提供了哪些基本操作

       3.这些操作的复杂度是多少

       1.列表在内存中以一块连续的空间存放,列表中存放的是每个元素的引用

       2.

        新增:insert,append

        删除:remove,pop

          修改:根据索引修改

          遍历,查找

      3.

         insert O(n),append O(1)

         remove O(n),pop O(1)

         修改 O(1)

         遍历 O(n)

         查找 O(n)

    二.栈:栈是一种数据集合,可以理解为只在一端进行插入或删除操作的列表

        特点:后进先出

        基本操作:

                     进栈:push

                     出栈:pop

                     取栈顶元素:gettop

      在python中只需要用列表就可以实现栈,创建列表li=[]

                     进栈:append

                     出栈:pop

                     取栈顶元素:li[-1]

    栈的应用:

      括号匹配问题,给一个字符串中,其中包含(,[,{ 判断该字符串中的括号是否匹配.例 ()()[]{} √,([{()}]) √,[]( X,[(]) X

           思路:循环字符串,创建一个空栈,如果字符串中游匹配的字符,放入栈中,如果找到相匹配的括号,将这对括号出栈

    def check_kuohao(s):
        stack = []
        for char in s:
            #判断字符串中如果有括号则放入栈中
            if char in {'(','[','{'}:
                stack.append(char)
            #如果匹配到括号,如果栈不为空,且栈顶有括号与之匹配,则将该元素出栈
            elif char == ')':
                if len(stack) > 0 and stack[-1] == '(':
                    stack.pop()
                else:
                    return False
            elif char == ']':
                if len(stack) > 0 and stack[-1] == '[':
                    stack.pop()
                else:
                    return False
            elif char == '}':
                if len(stack) > 0 and stack[-1] == '{':
                    stack.pop()
                else:
                    return False
        #如果栈为空表示所有括号匹配成功,否则失败
        if len(stack) == 0:
            return True
        else:
            return False
    View Code

     三.队列:队列是一种数据集合,仅允许在列表的一端进行插入,另一端进行删除.

                 插入队列的一端称为队尾,动作称为入队

                 删除队列的一端称为对头,动作称为出队

                 性质:先进先出

         双向队列:队列的两头都允许进行出队和入队

                 使用方法: from collections import deque

                 创建队列: queue = deque()

                 进队:append

                 出队:popleft

                 双向队列队首进队:appendleft

                 双向队列队尾进队:pop

         实现原理:

                初步设想:列表+两个下标指针

                实现:创建一个列表和两个变量,front指向队首,rear指向队尾,初始都为0

                进队操作:元素写到li[rear]的位置,rear自增1

                出队操作:返回li[front]的位置,front自减1


        算法实现:环形队列

                当队尾指针front==Maxsize+1时,在前进一个位置就自动到0

                实现方式求余运算

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

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

                      3.队空条件: rear == front

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

     四.链表:链表中每一个元素都是一个对象,每个对象称为一个节点,包含数据域和指针域,通过各个节点的相互链接,最终串成一个链表

         节点定义:

    class Node(object):
        def __init__(self,item):
            self.item = item
            self.next = None
    
    a = Node(10)
    b = Node(20)
    c = Node(30)
    
    #通过next将元素一个一个串起来
    a.next = b
    b.next = c
    print(a.item)
    print(a.next.item)#通过next访问下一个节点
    print(a.next.next.item)
    View Code

        遍历:

    1 def travle_sal(head):
    2     curNode = head
    3     while curNode is not None:
    4         print(curNode.item)
    5         curNode = curNode.next
    View Code

       插入:

       p.next = curNode.next

       curNode.next = p

      删除:

      p = curNode.next

      curNode.next = curNode.next.next

      del p

     

     建立链表

         1.头插法

    1 def createLinkListF(li):
    2     l = Node() #head
    3     for num in li:
    4         s = Node(num)
    5         s.next = l.next
    6         l.next = s
    7     return l
    View Code

         2.尾插法

    1 def createLinkListF(li):
    2     l = Node()
    3     r = l
    4     for num in li:
    5         s = Node(num)
    6         r.next = s
    7         r = s 
    View Code

     双向链表

          双向链表的每一个节点有两个指针,一个指向右节点,一个指向左节点

          节点定义

    1 class Node(object):
    2     def __init__(self,item):
    3         self.item = item
    4         self.next = None
    5         self.prior = None
    View Code

       插入

       p.next = curNode.next

       curNode.next.prior = p

       p.prior = curNode

       curNode.next = p

      删除

      p = curNode.next

      curNode.next = p.next

      p.next.prior = curNode

      del p

    建立双向链表:

    1 def createLinkListR(li):
    2     l = Node()
    3     r = l
    4     for num in li:
    5         s = Node(num)
    6         r.next = s
    7         s.proir = r
    8         r = s
    9     return l,r
    View Code

    链表总结

      插入元素的时间复杂度 O(1)

      删除元素的时间复杂度 O(1)

           修改元素的时间复杂度 O(n)

           查看元素的时间复杂度 O(n)

    五,集合和字典

        集合和字典是基于哈希表来对元素进行查找

        哈希表是一种线性存储结构,通过每个对象k的关键字作为自变量,通过一个哈希函数h(k) ,把k映射到下标h(k)处,并将该对象存储到这个位置

        例如:集合{1,6,7,9},假设哈希函数h(k)使得h(1) = 0,h(6)=2,h(7)=4,h(9)=5,那么哈希表被存储为[1,None,6,None,7,9],当我们查找元素6所在的位置

                时,通过哈希函数获得该元素所在的下标,因此在2的位置可以找到该元素

       python中的字典

       例如 a={'name':'alex','age':18,'gender':'Male'}

       使用哈希表存储字典,通过哈希函数将字典的key映射为下标.假设h('name') = 3,h('age') = 1,h('gender')=4,则哈希表存储为[None,18,None,'alex','Male']

       在字典键值对数量不多的情况下,基本上不会发生哈希冲突,此时查找一个元素的复杂度是O(1)

       哈希冲突:

           由于哈希表的下标范围是有限的,而元素的关键字的值是无限的,可能会出现h(23)=56,h(1990)=56的情况,此时两个元素映射到同一个下标处,这种情况

       称为哈希冲突

       解决哈希冲突的方法

          1.拉链法:将所有冲突的元素用链表连接

          2.开发寻址法:通过哈希冲突函数得到新的地址

      

     练习

       给一个二维列表,表示迷宫,(0,通,1,阻) 给出算法,求出走出迷宫的路径

      

    方法1:使用栈

    思路:从上一个节点开始,任意找下一个能走的节点,当找到不能走的节点时,退回到上一个节点,寻找是否有其他方向的点

    方法:创建一个栈,首先将入口的位置进栈,当栈不空时候循环,获取栈顶元素,寻找下一个可走的相邻方块,如果找不到可走的相邻方块,说明当前是死路,

             进行回溯(将当前的点出栈,查看前面的点是否还有其他出路),体现深度优先的思想

     1 maze=[
     2     [1,1,1,1,1,1,1,1,1,1],
     3     [1,0,0,1,0,0,0,1,0,1],
     4     [1,0,0,1,0,0,0,1,0,1],
     5     [1,0,0,0,0,1,1,0,0,1],
     6     [1,0,1,1,1,0,0,0,0,1],
     7     [1,0,0,0,1,0,0,0,0,1],
     8     [1,0,1,0,0,0,1,0,0,1],
     9     [1,0,1,1,1,0,1,1,0,1],
    10     [1,1,0,0,0,0,0,0,0,1],
    11     [1,1,1,1,1,1,1,1,1,1],
    12 ]
    13 
    14 #方向 上右下左
    15 dirs = [lambda x,y:(x+1,y),
    16         lambda x,y:(x-1,y),
    17         lambda x,y:(x,y-1),
    18         lambda x,y:(x,y+1)]
    19 
    20 def mpath(x1,y1,x2,y2):
    21     stack = []
    22     stack.append((x1,y1))
    23     while len(stack) > 0:
    24         curNode = stack[-1]
    25         #找到终点
    26         if curNode[0] == x2 and curNode[1] == y2:
    27             for p in stack:
    28                 print(p)
    29             return True
    30         for dir in dirs:
    31             nextNode = dir(*curNode)
    32             #此路通的
    33             if maze[nextNode[0]][nextNode[1]] == 0:
    34                 stack.append(nextNode)
    35                 #标记已走过的方格
    36                 maze[nextNode[0]][nextNode[1]] = -1
    37                 break
    38         else:
    39             maze[nextNode[0]][nextNode[1]] = -1
    40             stack.pop()
    41     return False
    42 
    43 mpath(1,1,8,8)
    View Code

    方法2:使用队列

    思路:从一个节点开始寻找,寻找下面能继续走的点,继续寻找直到能找出出口

    方法:创建一个空队列,将起点位置入队,在队列不空时循环,出队一次,如果相邻的位置为出口,则结束.否则找出4个相邻方块中可走的方块,全部入队

             体现广度优先的思想

     1 from collections import deque
     2 
     3 maze=[
     4     [1,1,1,1,1,1,1,1,1,1],
     5     [1,0,0,1,0,0,0,1,0,1],
     6     [1,0,0,1,0,0,0,1,0,1],
     7     [1,0,0,0,0,1,1,0,0,1],
     8     [1,0,1,1,1,0,0,0,0,1],
     9     [1,0,0,0,1,0,0,0,0,1],
    10     [1,0,1,0,0,0,1,0,0,1],
    11     [1,0,1,1,1,0,1,1,0,1],
    12     [1,1,0,0,0,0,0,0,0,1],
    13     [1,1,1,1,1,1,1,1,1,1],
    14 ]
    15 
    16 #方向 上右下左
    17 dirs = [lambda x,y:(x+1,y),
    18         lambda x,y:(x-1,y),
    19         lambda x,y:(x,y-1),
    20         lambda x,y:(x,y+1)]
    21 
    22 def mpath(x1,y1,x2,y2):
    23     queue = deque()
    24     path = []
    25     queue.append((x1,y1,-1))
    26     while len(queue) > 0:
    27         curNode = queue.popleft()
    28         path.append(curNode)
    29         if curNode[0] == x2 and curNode[1] == y2:
    30             print_p(path)
    31             return True
    32 
    33         for dir in dirs:
    34             nextNode = dir(curNode[0],curNode[1])
    35             if maze[nextNode[0]][nextNode[1]] == 0:
    36                 queue.append((*nextNode,len(path)-1))
    37                 maze[nextNode[0]][nextNode[1]] = -1
    38     return False
    39 
    40 def print_p(path):
    41     curNode = path[-1]
    42     realpath = []
    43     while curNode[2] != -1:
    44         realpath.append(curNode[0:2])
    45         curNode = path[curNode[2]]
    46     realpath.append(curNode[0:2])
    47     realpath.reverse()
    48     print(realpath)
    49 
    50 mpath(1,1,8,8)
    View Code

             

     

  • 相关阅读:
    NSUserDefaults存储自定义类
    beginBackgroundTaskWithExpirationHandle
    instancetype
    #define const extern
    singleton
    报错:说改变了系统文件。解决方法
    不合法语句 self.contentView.frame.origin.x = x;
    google应用商店的解决
    笔记
    读流testDemo
  • 原文地址:https://www.cnblogs.com/luhuajun/p/7358947.html
Copyright © 2020-2023  润新知