Python——数据结构(栈,队列,链表)

数据结构

程序=数据结构+算法

数据结构就是设计数据以何种方式组织并存储在计算机中。列表、集合与字典等都是一种数据结构。

小Tips:列表中的元素是怎样存储的,操作的时间复杂度是多少?

Python将数存放在一个内存单元中,在列表中的元素指向那个内存单元。所以列表中的元素在内存单元中可能在一起,也可能不在一起。

[].insert()和[].remove()的时间复杂度为o(n)
[].append()和[].pop()的时间复杂度为o(1)

栈(Stack)是一个数据集合,可以理解为只能在一端进行插入或删除操作的列表。

栈的特点:后进先出

栈的基本操作:

  • 进栈(压栈):push
  • 出栈:pop
  • 取栈顶(看看栈顶是谁):gettop 

Python中实现栈:

进栈函数:append
出栈函数:pop
查看栈顶函数:li[-1]

小Tips:

递归出错的原因是:爆栈

示例:给一个字符串,其中包含小括号、中括号、大括号,求该字符串中的括号是否匹配。

思路:检查字符串是否包含"{","[","("如果包含则将其入栈,遇到"}","]",")"时检查当前栈顶,相同则将其出栈,否则返回False

 1 def check_kuohao(str):
 2     stack = []
 3     for i in str:
 4         if i in {'{','[','('}:
 5             stack.append(i)
 6         elif i == '}':
 7             if len(stack) > 0 and stack[-1] == '{':
 8                 stack.pop()
 9             else:
10                 return False
11         elif i == ']':
12             if len(stack) > 0 and  stack[-1] == '[':
13                 stack.pop()
14             else:
15                 return False
16         elif i == ')':
17             if len(stack) > 0 and stack[-1] == '(':
18                 stack.pop()
19             else:
20                 return False
21 
22     if len(stack) == 0:
23         return True
24     else:
25         return False
26 
27 print(check_kuohao('([)]'))
View Code

示例:迷宫问题(深度优先,一条路走到黑)

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]
]

def mazepath(x1,y1,x2,y2):
    dirs = [
            # lambda 参数1,参数2:(返回值格式)
            lambda x, y: (x + 1, y),    # 向下走一格
            lambda x, y: (x - 1, y),    # 向上走一格
            lambda x, y: (x, y - 1),    # 向左走一格
            lambda x, y: (x, y + 1)     # 向右走一格
            ]
    stack = []    # 初始化一个栈
    stack.append((x1,y1))   # 将起始坐标推入栈中
    while len(stack) > 0:
        curNode = stack[-1]     # 查看栈顶元素
        if curNode[0] == x2 and curNode[1] == y2:   # 到达终点
            for i in stack:
                print(i)
            return True
        else:
            for d in dirs:
                nextNode = d(curNode[0],curNode[1])     # 将()中的元素做相应的操作,还没推入栈中
                if maze[nextNode[0]][nextNode[1]] == 0:    # 这条路可以走
                    stack.append(nextNode)  # 将这个新位置入栈
                    maze[nextNode[0]][nextNode[1]] = -1  # 将新位置标记为已经走过,防止死循环
                    break
            else:   # 当前位置上下左右都不能走,后退一步
                stack.pop()
    return False    # 栈为空,无路可走

print(mazepath(1,1,8,8))

队列

队列(Queue)是一个数据集合,仅允许在列表的一端进行插入,另一端进行删除。

进行插入的一端称为队尾(rear),插入动作称为进队或入队,进行删除的一端称为队头(front),删除动作称为出队

队列的性质:先进先出

双向队列:队列的两端都允许进行进队和出队操作。

队列的实现原理:

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

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

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

出队操作:返回li[front]的元素,front自减1。

这样队列会不够用,所以我可以把它的首尾连接起来。

环形队列:

实现方式:求余数运算

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

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

队空条件:rear == front

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

Python实现队列:

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

示例:迷宫问题(广度优先)

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

 1 from collections import  deque
 2 
 3 mg = [
 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,1,0,1],
13     [1,1,1,1,1,1,1,1,1,1]
14 ]
15 
16 dirs = [lambda x, y: (x + 1, y),
17         lambda x, y: (x - 1, y),
18         lambda x, y: (x, y - 1),
19         lambda x, y: (x, y + 1)]
20 
21 def print_p(path):
22     curNode = path[-1]
23     realpath = []
24     print('迷宫路径为:')
25     while curNode[2] != -1:
26         realpath.append(curNode[0:2])
27         curNode = path[curNode[2]]
28     realpath.append(curNode[0:2])
29     realpath.reverse()
30     print(realpath)
31 
32 def mgpath(x1, y1, x2, y2):
33     queue = deque()
34     path = []
35     queue.append((x1, y1, -1))
36     while len(queue) > 0:
37         curNode = queue.popleft()
38         path.append(curNode)
39         if curNode[0] == x2 and curNode[1] == y2:
40             #到达终点
41             print_p(path)
42             return True
43         for dir in dirs:
44             nextNode = dir(curNode[0], curNode[1])
45             if mg[nextNode[0]][nextNode[1]] == 0:  # 找到下一个方块
46                 queue.append((*nextNode, len(path) - 1))
47                 mg[nextNode[0]][nextNode[1]] = -1  # 标记为已经走过
48     return False
49 
50 
51 mgpath(1,1,8,8)
View Code

链表

链表中每一个元素都是一个对象,每个对象称为一个节点,包含有数据域key和指向下一个节点的指针next。通过各个节点之间的相互连接,最终串联成一个链表。

定义节点:

class Node(object):
    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  

链表节点的插入和删除

插入:
p.next = curNode.next
curNode.next = p

删除:
p = curNode.next
curNode.next = curNode.next.next
del p

建立链表:

头插法

def createLinkListF(li):
    l = Node()
    for num in li:
        s = Node(num)
        s.next = l.next
        l.next = s
    return l  

尾插法

def createLinkListR(li):
    l = Node()
    r = l       #r指向尾节点
    for num in li:
        s = Node(num)
        r.next = s
        r = s

双链表

双链表中每个节点有两个指针:一个指向后面节点、一个指向前面节点。
节点定义:

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

插入和删除 

插入:
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

建立双链表

def createLinkListR(li):
    l = Node()
    r = l
    for num in li:
        s = Node(num)
        r.next = s
        s.prior = r
        r = s
    return l, r

 

posted @ 2017-11-29 20:43  想54256  阅读(901)  评论(0编辑  收藏  举报