文章目录
- 10.1 栈和队列
- 练习
- 10.1-1
- 10.1-2
- 10.1-3
- 10.1-6(两个栈实现一个队)
- 10.1-7(两个队实现一个栈)
- 10.2 链表
- 练习
- 10.2-1(单链表删除和插入操作在o(1)时间)
- 10.2-2(单链表实现栈,头插头出)
- 10.2-3 单链表实现队列(尾插头出)
- 10.2-4
- 10.2-5 使用单向循环链表表实现字典
- 10.2-6(合并两个双向循环链表)
- 10.2-7(翻转单向链表)
- 10.4有根树的表示
- 练习
- 10.4-1
- 10.4-2
- 10.4-3 (使用队列作为辅助结构实现二叉树结点的输出)
- 10.4-3(栈作辅助输出二叉树的元素)
- 10.4-4(输出左子右兄表示的二叉树元素)
10.1 栈和队列
1、栈:先进后出
2、队列:先进先出
3、上溢(overflow):栈或队列已经满了,仍往其中加元素
4、下溢(underflow):栈或队列已经空了,仍执行弹出操作
class Stack(object):
def __init__(self, limit=3):
self.stack = [] # 存放元素
self.limit = limit # 栈容量极限
def push(self, data): # 判断栈是否溢出
if len(self.stack) >= self.limit:
raise IndexError('栈已满')
self.stack.append(data)
def pop(self):
if self.stack:
return self.stack.pop()
else:
raise IndexError('pop from an empty stack') # 空栈不能被弹出
def peek(self): # 查看堆栈的最上面的元素
if self.stack:
return self.stack[-1]
def is_empty(self): # 判断栈是否为空
return not bool(self.stack)
def size(self): # 返回栈的大小
return len(self.stack)
class Queue:
def __init__(self, limit=4):
self.items = []
self.limit = limit
def enqueue_head(self, item):
if len(self.items) == self.limit: # 上溢
raise IndexError('队列已满')
self.items.insert(0, item)
self.items.append(item)
def enqueue_tail(self, item):
if len(self.items) == self.limit: # 上溢
raise IndexError('队列已满')
self.items.append(item)
def dequeue_head(self):
if len(self.items) == 0:
raise IndexError("空队列不能弹出") # 下溢
return self.items.pop(0)
def dequeue_tail(self):
if len(self.items) == 0:
raise IndexError("空队列不能弹出") # 下溢
return self.items.pop(-1)
def empty(self):
return self.size() == 0
def size(self):
return len(self.items)
q = Queue()
q.enqueue_head(1)
q.enqueue_head(2)
q.enqueue_tail(3)
q.enqueue_tail(4)
q.dequeue_head()
q.dequeue_tail()
q.dequeue_head()
print(q.size())
st = Stack()
st.push(1)
st.push(2)
st.push(3)
st.pop()
st.pop()
print(st.pop())
st.pop()
练习
10.1-1
10.1-2
A栈从1开始向增长
B栈从开始向1前进
当推入一个元素两个栈的指针相邻
10.1-3
10.1-6(两个栈实现一个队)
假设有栈和栈
入队时将所有元素都加入栈:
出队时将栈的元素弹出到栈,栈再弹出,涉及栈弹出时:
10.1-7(两个队实现一个栈)
假设有队和队
入栈时将所有元素都加入到队:
出栈时将队的元素弹出到队,当A队只剩下一个元素时再将该元素弹出:
10.2 链表
1、双向链表的每一个元素都是一个对象,每个对象有一个关键字key和两个指针prev和next。
2、要搜索一个有个元素的链表,search操作必须需要
3、插入操作为
4、仅删除操作需要,删除特定结点需要,因为要先通过search找到该元素
5、在循环语句中使用哨兵的好处仅在于提高了链表的代码的简洁度,并不会提高速度。
class Node(object):
"""双链表结点"""
def __init__(self, item=None):
self.item = item
self.prev = None
self.next = None
class BilateralLinkList(object):
def __init__(self, item=None):
self.head = Node(item)
def is_empty(self):
return self.head is None
def length(self):
"""链表长度"""
if self.is_empty():
return 0
n = 1
cur = self.head
while None != cur.next:
cur = cur.next
n += 1
return n
def ergodic(self):
"""遍历链表"""
if self.is_empty():
raise ValueError('ERROR NULL')
res = []
cur = self.head
res.append(cur.item)
while None != cur.next:
cur = cur.next
res.append(cur.item)
return res
def add(self, item):
"""在头部添加节点"""
node = Node(item)
if self.is_empty():
self.head = node
else:
node.next = self.head
self.head.prev = node
self.head = node
def append(self, item):
"""在尾部添加节点"""
if self.is_empty():
self.add(item)
else:
node = Node(item)
cur = self.head
while None != cur.next:
cur = cur.next
cur.next = node
node.prev = cur
def insert(self, index, item):
"""在任意位置插入节点"""
if index == 0:
self.add(item)
elif index + 1 >= self.length():
self.append(item)
else:
n = 1
node = Node(item)
cur = self.head
while node != cur.next:
pre = cur
cur = cur.next
n += 1
if n == index:
break
pre.next = node
node.prev = pre
node.next = cur
cur.prev = node
def Search(self, k):
"""链表的搜素"""
""":return 指向k的指针"""
cur = self.head
while cur and cur.item != k:
cur = cur.next
return cur
def remove(self):
"""删除头结点"""
if self.is_empty():
return False
cur = self.head.next
self.head = self.head.next
self.head.prev = None
def find_tail(self):
"""找到并指向尾结点"""
if self.is_empty():
return False
cur = self.head
while cur.next != None:
cur = cur.next
return cur
def delete(self, k):
"""删除结点"""
if self.is_empty():
return False
elif self.head.item == k: # 删除头结点
return self.remove()
elif self.find_tail().item == k:
pre = self.find_tail().prev # 删除尾结点
pre.next = None
else:# 删除中间结点
pre1 = self.Search(k)
pre1.prev.next = pre1.next
pre1.next.prev = pre1.prev
b = BilateralLinkList(1)
b.add(0)
b.add(-1)
b.append(2)
print(b.ergodic())
b.insert(4, 3) # 末端插入情况
print("末端插入:", b.ergodic())
b.insert(2, 1.5) # 中间插入情况
print("中间插入:", b.ergodic())
b.insert(0, -2) # 头插入情况
print("头插入:", b.ergodic())
print(b.ergodic())
b.remove() # 删除头结点
print("删除头", b.ergodic())
b.delete(0) # 删除尾结点
print("删除中间", b.ergodic())
b.delete(3) # 删除尾结点
print("删除尾", b.ergodic())
练习
10.2-1(单链表删除和插入操作在o(1)时间)
都可以
插入A: 让A指向链表的头部,然后让头指针指向A
删除 C: 将C的next的值赋给C,然后C指向C的next的next
10.2-2(单链表实现栈,头插头出)
class Node(object):
"""单表结点"""
def __init__(self, item=None):
self.item = item
self.next = None
class Linklist():
def __init__(self, item=None):
self.head = Node(item)
def STACK_EMPTY(self):
return self.head.item is None
def PUSH(self, x):#头插
x = Node(x)
x.next = self.head
self.head = x
def POP(self):
if self.STACK_EMPTY():
raise IndexError("underflow")
x = self.head.item
self.head = self.head.next
return x
a = Linklist()
a.PUSH(1)
a.PUSH(2)
a.PUSH(3)
print(a.POP())
10.2-3 单链表实现队列(尾插头出)
class Node(object):
"""单表结点"""
def __init__(self, item=None):
self.item = item
self.next = None
"""单链表实现队列"""
class Linklist():
def __init__(self):
self.head = None
def QUEUE_EMPTY(self):
return self.head is None
def ENQUEUE(self, x):#尾插
x = Node(x)
if self.QUEUE_EMPTY():
self.head = x
else:
cur = self.head
while cur and cur.next:
cur = cur.next
cur.next = x
def DEQUEUE(self):#头出
if self.QUEUE_EMPTY():
raise IndexError("underflow")
x = self.head.item
self.head = self.head.next
return x
a = Linklist()
a.ENQUEUE(1)
a.ENQUEUE(2)
a.ENQUEUE(3)
a.ENQUEUE(4)
print(a.DEQUEUE())
print(a.DEQUEUE())
print(a.DEQUEUE())
print(a.DEQUEUE())
print(a.QUEUE_EMPTY())
10.2-4
因为知道所以循环的时候就可将这两行代码合并为
10.2-5 使用单向循环链表表实现字典
class Node(object):
"""单表结点"""
def __init__(self, item=None):
self.item = item
self.next = None
"""单链表实现队列"""
class Linklist():
def __init__(self):
self.head = Node()
self.size = 0 # 因为有哨兵结点的存在
def QUEUE_EMPTY(self):
return self.size == 0
"""O(1)"""
def INSERT(self, x):# 头插
x = Node(x)
x.next = self.head.next
self.head.next = x
self.size += 1
"""O(n)"""
def DELETE(self, x):
prev = self.head
while prev.next.item != x:
if prev.next == self.head:
print("the element is not exist")
prev = prev.next
prev.next = prev.next.next
self.size -= 1
"""O(n)"""
def SEARCH(self, k):
cur = self.head
while cur.next != self.head and cur.item != k:
cur = cur.next
return cur
a = Linklist()
a.INSERT(1)
a.INSERT(2)
a.INSERT(3)
print(a.QUEUE_EMPTY())
a.DELETE(1)
a.DELETE(2)
print(a.SEARCH(3))
a.DELETE(3)
print(a.QUEUE_EMPTY())
10.2-6(合并两个双向循环链表)
10.2-7(翻转单向链表)
需要三个指针:
定位当前元素,定位前一个元素,定位后一个元素
10.4有根树的表示
练习
10.4-1
10.4-2
##TreeNode定义
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
def __str__(self):
return f'(root: {self.val}-[left: {self.left}, right: {self.right}])'
def PRINT_BINARY_TREE(root):
x = root
if x != None:
PRINT_BINARY_TREE(x.left)
print(x.val)
PRINT_BINARY_TREE(x.right)
root = TreeNode(18)
root.left = TreeNode(12)
root.right = TreeNode(10)
root.left.left = TreeNode(7)
root.left.right = TreeNode(4)
root.right.left = TreeNode(2)
root.right.right = TreeNode(21)
root.left.right.left = TreeNode(5)
print(root)
PRINT_BINARY_TREE(root)
"""定义结点"""
class Node(object):
def __init__(self, item):
self.item = item
self.left = None
self.right = None
class Binary_tree(object):
def __init__(self):
self.root = None
"""树中添加元素"""
def add(self, item):
node = Node(item)
queue = [self.root] # 用队列存储根结点
if self.root is None:
self.root = node
return
while queue:
cur_node = queue.pop(0)
if cur_node.left is None:
cur_node.left = node
return
else:
queue.append(cur_node.left)
if cur_node.right is None:
cur_node.right = node
return
else:
queue.append(cur_node.right)
"""先序遍历"""
def preorder(self, root):
if root is None:
return
print(root.item, end=" ")
self.preorder(root.left)
self.preorder(root.right)
"""中序遍历"""
def inorder(self, root):
if root is None:
return
self.inorder(root.left)
print(root.item, end=" ")
self.inorder(root.right)
"""后序遍历"""
def afterorder(self, root):
if root is None:
return
self.afterorder(root.left)
self.afterorder(root.right)
print(root.item, end=" ")
Tree = Binary_tree()
Tree.add(18)
Tree.add(12)
Tree.add(10)
Tree.add(7)
Tree.add(4)
Tree.add(2)
Tree.add(21)
Tree.add(5)
Tree.preorder(Tree.root)#18 12 7 5 4 10 2 21
print(":先序")
Tree.inorder(Tree.root)#5 7 12 4 18 2 10 21
print(":中序")
Tree.afterorder(Tree.root)#5 7 4 12 2 21 10 18
print(":后序")
10.4-3 (使用队列作为辅助结构实现二叉树结点的输出)
"""定义结点"""
class Node(object):
def __init__(self, item):
self.item = item
self.left = None
self.right = None
class Binary_tree(object):
def __init__(self):
self.root = None
"""树中添加元素"""
def add(self, item):
node = Node(item)
queue = [self.root] # 用队列存储根结点
if self.root is None:
self.root = node
return
while queue:
cur_node = queue.pop(0)
if cur_node.left is None:
cur_node.left = node
return
else:
queue.append(cur_node.left)
if cur_node.right is None:
cur_node.right = node
return
else:
queue.append(cur_node.right)
"""
按层输出树中的元素
非递归0(n),队列作为辅助数据结构
"""
def breath_travel(self):
if self.root is None:
return
queue = [self.root]
while queue:
cur_node = queue.pop(0)
print(cur_node.item, end=" ")
if cur_node.left is not None:
queue.append(cur_node.left)
if cur_node.right is not None:
queue.append(cur_node.right)
Tree = Binary_tree()
Tree.add(18)
Tree.add(12)
Tree.add(10)
Tree.add(7)
Tree.add(4)
Tree.add(2)
Tree.add(21)
Tree.add(5)
Tree.breath_travel()#18 12 10 7 4 2 21 5 :层序
print(":层序")
10.4-3(栈作辅助输出二叉树的元素)
"""定义结点"""
class Node(object):
def __init__(self, item):
self.item = item
self.left = None
self.right = None
class Binary_tree(object):
def __init__(self):
self.root = None
"""树中添加元素"""
def add(self, item):
node = Node(item)
queue = [self.root] # 用队列存储根结点
if self.root is None:
self.root = node
return
while queue:
cur_node = queue.pop(0)
if cur_node.left is None:
cur_node.left = node
return
else:
queue.append(cur_node.left)
if cur_node.right is None:
cur_node.right = node
return
else:
queue.append(cur_node.right)
"""
按层输出树中的元素
非递归0(n),栈作为辅助数据结构
"""
def breath_travel(self):
if self.root is None:
return
Stack = [self.root]
while Stack:
cur_node = Stack.pop()
print(cur_node.item, end=" ")
"""因为栈是后入先出所以先检查右边的再检查左边的
输出的时候就会先左子后右子"""
if cur_node.right is not None:
Stack.append(cur_node.right)
if cur_node.left is not None:
Stack.append(cur_node.left)
Tree = Binary_tree()
Tree.add(18)
Tree.add(12)
Tree.add(10)
Tree.add(7)
Tree.add(4)
Tree.add(2)
Tree.add(21)
Tree.add(5)
Tree.breath_travel()
10.4-4(输出左子右兄表示的二叉树元素)
"""定义结点"""
class Tree:
def __init__(self, val):
self.val = val
self.left_child = None
self.right_bro = None
class Solution:
def getAllNodeFromTreeByStack(self):
if not self:
return []
resList, stack = [], list()
stack.append(self)
while stack:
node = stack.pop()
resList.append(node.val)
if node.right_bro:
stack.append(node.right_bro)
if node.left_child:
stack.append(node.left_child)
return resList
tree = Tree(0)
tree.left_child = Tree(10)
tree.left_child.right_bro = Tree(12)
tree.left_child.right_bro.right_bro = Tree(-1)
tree.left_child.right_bro.right_bro.right_bro = Tree(93)
tree.left_child.right_bro.right_bro.right_bro.left_child = Tree(100)
print(Solution.getAllNodeFromTreeByStack(tree))