基础数据结构的python实现----队列、栈、链表、二叉树
文章目录
1 队列-Queue
#队列:先进先出
class Queue():
def __init__(self):
self.items = []
#进入队列
def enqueue(self, item):
self.items.append(item)
#出队列
def dequeue(self):
return self.items.pop(0)
#遍历队列元素
def travel(self):
for i in self.items:
print(i)
#获取队列长度
def size(self):
count = 0
for i in self.items:
count += 1
return count
queue = Queue()
queue.enqueue(1)
queue.enqueue(2)
queue.enqueue(3)
queue.enqueue(4)
queue.travel()
2 栈-Stack
#栈堆: 先进后出
class Stack():
def __init__(self):
self.items = []
#进入队列
def enstack(self, item):
self.items.append(item)
#出队列
def destack(self):
return self.items.pop()
#遍历栈元素
def travel(self):
lenth = len(self.items)
for i in range(lenth):
print(self.items[lenth - i - 1])
stack = Stack()
stack.enstack(1)
stack.enstack(2)
stack.enstack(3)
stack.enstack(4)
stack.destack()
stack.travel()
2.1 两个队列实现一个栈
两个队列实现栈。获取两个,queue1 和 queue2。
- 进栈:都将数据输入queue1中;
- 出栈:将queue1的除了最后一个数据之外的都转移到queue2中,输出queue1的剩下的元素,即出栈;
- queue1 和 queue2交换。
#用两个队列实现一个栈
class MyStack():
def __init__(self):
#初始化两个queue
self.queue1 = Queue()
self.queue2 = Queue()
#进栈
def Enstack(self, item):
self.queue1.enqueue(item)
#出栈
def Destack(self):
if self.size() == 1:
return self.queue1.dequeue()
if self.size() > 1:
while self.size() > 1:
item = self.queue1.dequeue()
self.queue2.enqueue(item)
self.queue1 , self.queue2 = self.queue2, self.queue1
return self.queue2.dequeue()
def size(self):
return self.queue1.size()
#遍历栈
def travel(self):
for i in range(self.size()):
print(self.Destack())
mystack = MyStack()
mystack.Enstack(1)
mystack.Enstack(2)
mystack.Enstack(3)
mystack.Enstack(4)
mystack.Enstack(5)
mystack.travel()
'''
output:
5
4
3
2
1
'''
#做到了先进后出
队列(queue)和栈(stack)表示在内存中,都是开辟的一整块连续的空间,对应查找比较方便:时间复杂度O(1);但是增删比较麻烦,时间复杂度为O(n)。
3 链表-Link
单向链表相比队列和栈,每个数据节点多了一个指针,指向下一个节点的地址。因此链表的内存空间并不是连续的开辟的一块,而是离散分布的一个个小节点内存块,批次通过指针连接起来。对应的增删比较方便,时间复杂度为O(1),查找麻烦,时间复杂度为O(n)。
3.1 单向链表
#先定义节点,每个节点Node包含两个属性:数据(item) + 地址指针(next)
class Node():
def __init__(self, item):
self.item = item
self.next = None
class Link():
def __init__(self):
#构造一个空链表
#_head 存储的只能是空或者头节点的地址
self._head = None
#向链表的头部插入一个节点
def add(self, item):
#创建一个新节点
node = Node(item)
#将原来头节点的地址赋给这个新节点的next
node.next = self._head
#这个新增的节点为头节点,因此_head指向它
self._head = node
#遍历链表所有元素
def travel(self):
#从头节点开始,当节点不为空,则继续next
node = self._head
while node:
print(node.item)
node = node.next
#是否为空
def isEmpty(self):
return False if self._head else True
#有多少个节点
def size(self):
count = 0
node = self._head
while node:
count = count + 1
node = node.next
return count
#向链表尾部添加一个Node
def append(self, item):
node = Node(item)
#当链表为空时
if self.isEmpty():
self._head = node
#当链表不为空时
else:
pre = None
cur = self._head
while cur:
pre = cur
cur = cur.next
pre.next = node
#search指定item在链表中哪个位置,返回一个位置list,如果没有,则为空列表
def search(self, item):
indexs = []
count = 0
node = self._head
while node:
if item == node.item:
indexs.append(count)
count = count + 1
node = node.next
if len(indexs) == 0:
print(False)
return None
else:
print(True)
return indexs
#在指定位置插入节点
def insert(self, index, item):
#确定要插入的位置坐标是否大于原有链表长度
ori_size = self.size()
if index > ori_size:
print('index out of link range!')
else:
if index == 0 or ori_size == 0:
self.add(item)
elif index == ori_size:
self.append(item)
else:
node = Node(item)
pre = self._head
for i in range(1,index):
pre = pre.next()
node.next = pre.next
pre.next = node
#移除指定位置的节点
def remove_index(self, index):
if index == 0:
self._head = self._head.next
else:
pre = None
cur = self._head
for i in range(index):
pre = cur
cur = cur.next
pre.next = cur.next
#移除指定数值的所有节点
def remove_item(self, item):
#先获取该item在链表中的所有indexs, 之后挨个删除
indexs = self.search(item)
if len(indexs) == None:
print('item not in link')
return False
else:
count = 0
for index in indexs:
index = index - count
self.remove_index(index)
count += 1
#链表反向排序
def reverse(self):
pre = None
cur = self._head
next_node = cur.next
while cur:
cur.next = pre
pre = cur
cur = next_node
if cur:
next_node = cur.next
else:
break
self._head = pre
link = Link()
link.append(4)
link.add(3)
link.add(5)
link.append(8)
link.add(10)
link.travel()
'''
output:
10
5
3
4
8
'''
3.2 双向链表
双向链表相比单向链表多了一个指向上一个节点的地址的指针。
#双链表
class Node():
#定义节点的头和尾
def __init__(self, item):
self.item = item
self.head = None
self.next = None
class DoubleLink():
def __init__(self):
self._head = None
#在头部节点插入
def add(self, item):
node = Node(item)
node.next = self._head
self._head = node
#在尾部节点插入
def append(self, item):
if self.size() == 0:
self.add(item)
else:
node = Node(item)
pre = None
cur = self._head
while cur:
pre = cur
cur = cur.next
pre.next = node
node.head = pre
#在某个index出插入
def insert(self, index, item):
ori_size = self.size()
if ori_size == 0 or index == 0:
self.add(item)
elif ori_size == index:
self.append(item)
else:
node = Node(item)
pre = None
cur = self._head
for i in range(0,index):
pre = cur
cur = cur.next
cur.head = node
node.next = cur
node.head = pre
pre.next = node
def travel(self):
cur = self._head
while cur:
print(cur.item)
cur = cur.next
def size(self):
count = 0
cur = self._head
while cur:
cur = cur.next
count += 1
return count
doublelink = DoubleLink()
doublelink.append(1)
doublelink.append(2)
doublelink.append(3)
doublelink.append(4)
doublelink.insert(2,5)
doublelink.travel()
'''
output:
1
2
5
3
4
'''
4 二叉树 + 广度(深度)优先节点遍历
二叉树是一种常见的树形数据结构,进一步了解可参考:数据结构和算法(十):二叉树
4.1 普通二叉树
#定义节点,每个节点有3个属性:数值 + 左指针 + 右指针
class Node():
def __init__(self,item):
self.item = item
self.left = None
self.right = None
#定义一个二叉树
class Tree():
def __init__(self):
self.root = None
#向树中添加节点:按层从左到右顺序插入
def add_node(self, item):
node = Node(item)
#无节点存在,则插入根节点
if self.root == None:
self.root = node
else:
List = [self.root]
while List:
q = List.pop(0)
if q.left == None:
q.left = node
break
else:
List.append(q.left)
if q.right == None:
q.right = node
break
else:
List.append(q.right)
#遍历树,按照添加节点顺序输出节点数值: 按层从左到右遍历 --- 广度优先遍历
def BFS_travel(self):
List = [self.root]
while List:
q = List.pop(0)
print(q.item)
if q.left != None:
List.append(q.left)
if q.right != None:
List.append(q.right)
#遍历树:深度优先算法:前序遍历 --根左右
def DFS_Forward(self, root):
if root != None:
print(root.item)
self.DFS_Forward(root.left)
self.DFS_Forward(root.right)
#深度优先算法:中序遍历 --左根右
def DFS_Middle(self, root):
if root != None:
self.DFS_Middle(root.left)
print(root.item)
self.DFS_Middle(root.right)
#深度优先算法:后序遍历 --左右根
def DFS_Backward(self, root):
if root != None:
self.DFS_Backward(root.left)
self.DFS_Backward(root.right)
print(root.item)
tree = Tree()
tree.add_node(1)
tree.add_node(2)
tree.add_node(3)
tree.add_node(4)
tree.add_node(5)
tree.add_node(6)
tree.add_node(7)
tree.add_node(8)
tree.BFS_travel()
'''
output: 1 2 3 4 5 6 7 8
'''
4.2 排序二叉树
#排序二叉树
class SortedTree():
def __init__(self):
self.root = None
#添加节点时:大于根节点的在右子节点,大小等于根节点的在左子节点
def add_node(self, item):
node = Node(item)
if self.root == None:
self.root = node
else:
cur = self.root
while True:
if item > cur.item:
if cur.right == None:
cur.right = node
break
else:
cur = cur.right
else:
if cur.left == None:
cur.left =node
break
else:
cur = cur.left
#遍历树,按照添加节点顺序输出节点数值: 按层从左到右遍历 --- 广度优先遍历
def BFS_travel(self):
List = [self.root]
while List:
q = List.pop(0)
print(q.item)
if q.left != None:
List.append(q.left)
if q.right != None:
List.append(q.right)
#遍历树:深度优先算法:前序遍历 --根左右
def DFS_Forward(self, root):
if root != None:
print(root.item)
self.DFS_Forward(root.left)
self.DFS_Forward(root.right)
#深度优先算法:中序遍历 --左根右
def DFS_Middle(self, root):
if root != None:
self.DFS_Middle(root.left)
print(root.item)
self.DFS_Middle(root.right)
#深度优先算法:后序遍历 --左右根
def DFS_Backward(self, root):
if root != None:
self.DFS_Backward(root.left)
self.DFS_Backward(root.right)
print(root.item)
sortedTree = SortedTree()
sortedTree.add_node(3)
sortedTree.add_node(8)
sortedTree.add_node(5)
sortedTree.add_node(7)
sortedTree.add_node(6)
sortedTree.add_node(2)
sortedTree.add_node(9)
sortedTree.add_node(4)
sortedTree.add_node(1)
print('DFS_Forward:')
sortedTree.DFS_Forward(sortedTree.root)
print('DFS_Middle:')
sortedTree.DFS_Middle(sortedTree.root)
print('DFS_Backward:')
sortedTree.DFS_Backward(sortedTree.root)
'''
output:
DFS_Forward: 3 2 1 8 5 4 7 6 9
DFS_Middle: 1 2 3 4 5 6 7 8 9
DFS_Backward: 1 2 4 6 7 5 9 8 3
'''
使用排序二叉树存储节点时,中序排列的结果一定为:递增的数组。
End:重温数据结构。后续将跟进对一些算法的理解和实现。