1、链表的封装
链表是一种物理存储单元上非连续、非顺序
的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。
每个结点包括两个部分:一个是存储数据元素的数据域
,另一个是存储下一个结点地址的指针域
。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
LeetCode题目:两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
- 请你将两个数相加,并以相同形式返回一个表示和的链表。
- 你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
输出
# 封装节点类
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def travel(self, head):
"""遍历链表里面的每一个元素"""
while head:
print(head.val, end='')
head = head.next
## 创建链表
def create_l1():
# l1 = 2,4,3
# l2 = 5, 6, 4
l1 = ListNode()
node1 = ListNode(val=2)
node2 = ListNode(val=4)
node3 = ListNode(val=3)
l1.next = node1
node1.next = node2
node2.next = node3
return l1.next
def create_l2():
# l1 = 2,4,3
# l2 = 5, 6, 4
l2 = ListNode()
node1 = ListNode(val=5)
node2 = ListNode(val=6)
node3 = ListNode(val=4)
l2.next = node1
node1.next = node2
node2.next = node3
return l2.next
def addTwoNumbers(l1: ListNode, l2: ListNode) -> ListNode: ## 两个链表中的数据对应相加,从左到右
res = 0
l3 = ListNode()
cur = l3
while(l1 or l2):
if(l1):
res += l1.val # res=2
l1 = l1.next
if(l2):
res += l2.val # res=2+5=7
l2 = l2.next
# res=10, val=0, res=>val val=res%10
# res=14, val=4, 14%10=4
l3.next = ListNode(res%10)
l3 = l3.next
# res=10, 进位为1, 10//10=1
# res=14, 进位为1, 14//10=1
res //= 10
if res == 1:
l3.next = ListNode(1)
return cur.next
if __name__ == '__main__':
l1 = create_l1()
l2 = create_l2()
l1.travel(l1)
l3=addTwoNumbers(l1,l2)
l3.travel(l3)
输出:708
2、栈和队列的封装
2.1 栈的封装
栈是限制在一端进行插入操作和删除操作的线性表(俗称堆栈),允许进行操作的一端称为“栈顶”,另一固定端称为“栈底”,当栈中没有元素时称为“空栈”。向一个栈内插入元素称为是进栈(push);从一个栈删除元素称为是出栈(pop)。特点 :后进先出(LIFO)
class Stack(object):
"""栈的封装[1, 2, 3, 4]"""
def __init__(self):
self.stack = []
def push(self, value):
"""入栈"""
self.stack.append(value)
print(f"入栈元素为{value}")
def pop(self):
"""出栈"""
if self.is_empty():
raise Exception("栈为空")
item = self.stack.pop()
print(f"出栈元素为{item}")
return item
def is_empty(self):
"""判断栈是否为空"""
return len(self.stack) == 0
def top(self):
"""返回栈顶元素"""
if self.is_empty():
raise Exception("栈为空")
return self.stack[-1]
def __len__(self):
"""魔术方法, len(object)自动执行的方法"""
return len(self.stack)
if __name__ == '__main__':
stack = Stack()
stack.push(1)
stack.push(2)
stack.push(3)
print(len(stack)) # 3
stack.pop()
print(stack.is_empty()) # False
print(stack.top()) # 2
输出:
入栈元素为1
入栈元素为2
入栈元素为3
3
出栈元素为3
False
2
2.2 队列的封装
队列是限制在一端进行插入操作和另一端删除操作的线性表,允许进行插入操作的一端称为“队尾”
允许进行删除操作的一端称为“队头”,当队列中没有元素时称为“空队”。特点 :先进先出(FIFO)。
class Queue(object):
"""队的封装[ 2, 3, 4]"""
def __init__(self):
self.queue = []
def enqueue(self, value):
"""入队"""
self.queue.append(value)
print(f"入队元素为{value}")
def dequeue(self):
"""出队"""
if self.is_empty():
raise Exception("队列为空")
item= self.queue.pop(0)
print(f"出队元素为{item}")
return item
def is_empty(self):
"""判断队列是否为空"""
return len(self.queue) == 0
def first(self):
"""返回队头元素"""
if self.is_empty():
raise Exception("队列为空")
return self.queue[0]
def last(self):
"""返回队尾元素"""
if self.is_empty():
raise Exception("队列为空")
return self.queue[-1]
def __len__(self):
"""魔术方法, len(object)自动执行的方法"""
return len(self.queue)
if __name__ == '__main__':
queue=Queue()
queue.enqueue(2)
queue.enqueue(3)
queue.enqueue(4)
queue.dequeue()
print(queue.is_empty())
print(queue.first())
print(queue.last())
输出:
入队元素为2
入队元素为3
入队元素为4
出队元素为2
False
3
4
3、二叉树封装
3.1 二叉树是啥
3.2 二叉树遍历方法
二叉树的遍历主要有三种:
方法一:前序遍历
前序遍历就是先遍历根节点,然后遍历左节点,最后是右节点;
方法二:中序遍历
中序遍历就是先遍历左节点,然后遍历中间的根节点,最后是右节点;
方法三:后序遍历
后序遍历就是先遍历左节点,然后遍历是右节点,最后是中间的根节点。
class Node(object):
"""节点类"""
def __init__(self, val=None, left=None, right=None):
self.val = val
self.left = left
self.right = right
class BinaryTree(object):
"""封装二叉树"""
def __init__(self, root):
self.root = root
def pre_travel(self, root):
"""先序遍历: 根左右"""
if (root != None):
print(root.val)
self.pre_travel(root.left)
self.pre_travel(root.right)
def in_travel(self, root):
"""中序遍历: 左根右"""
if (root != None):
self.in_travel(root.left)
print(root.val)
self.in_travel(root.right)
def last_travel(self, root):
"""后序遍历: 左右根"""
if (root != None):
self.last_travel(root.left)
self.last_travel(root.right)
print(root.val)
if __name__ == '__main__':
node1 = Node(1)
node2 = Node(2)
node3 = Node(3)
node4 = Node(4)
node5 = Node(5)
node6 = Node(6)
node7 = Node(7)
node8 = Node(8)
node9 = Node(9)
node10 = Node(10)
bt = BinaryTree(root=node1)
node1.left = node2
node1.right = node3
node2.left = node4
node2.right= node5
node3.left = node6
node3.right = node7
node4.left = node8
node4.right = node9
node5.left = node10
# 先序遍历
bt.pre_travel(node1)