二叉树
定义
二叉查找树(Binary Search Tree),又称为二叉搜索树、二叉排序树。其或者是一棵空树;或者是具有以下性质的二叉树:
- 若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值
- 若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值
- 左、右子树也分别为二叉排序树
树中节点的定义如下:
class Node:
def __init__(self, data):
self.data = data
self.lchild = None
self.rchild = None
实现一个二叉查找树,并且支持插入、删除、查找操作
参考:https://blog.csdn.net/u010089444/article/details/70854510
https://www.cnblogs.com/lilip/p/9937697.html
查找与插入
当二叉查找树不为空时:
首先将给定值与根结点的关键字比较,若相等,则查找成功
若小于根结点的关键字值,递归查左子树
若大于根结点的关键字值,递归查右子树
若子树为空,查找不成功
二叉排序树是一种动态树表。其特点是:树的结构通常不是一次生成的,而是在查找过程中,当树中不存在关键字等于给定值的结点时再进行插入。新插入的结点一定是一个新添加的叶子结点,并且是查找不成功时查找路径上访问的最后一个结点的左孩子或右孩子结点。如下图所示:
# 搜索
def search(self, node, parent, data):
if node is None:
return False, node, parent
if node.data == data:
return True, node, parent
if node.data > data:
return self.search(node.lchild, node, data)
else:
return self.search(node.rchild, node, data)
# 插入
def insert(self, data):
flag, n, p = self.search(self.root, self.root, data)
if not flag:
new_node = Node(data)
if data > p.data:
p.rchild = new_node
else:
p.lchild = new_node
删除
# 删除
def delete(self, root, data):
flag, n, p = self.search(root, root, data)
if flag is False:
print "无该关键字,删除失败"
else:
if n.lchild is None:
if n == p.lchild:
p.lchild = n.rchild
else:
p.rchild = n.rchild
del n
elif n.rchild is None:
if n == p.lchild:
p.lchild = n.lchild
else:
p.rchild = n.lchild
del n
else: # 左右子树均不为空
pre = n.rchild
if pre.lchild is None:
n.data = pre.data
n.rchild = pre.rchild
del pre
else:
next = pre.lchild
while next.lchild is not None:
pre = next
next = next.lchild
n.data = next.data
pre.lchild = next.rchild
del next
实现查找二叉查找树中某个节点的后继、前驱节点
参考:https://www.cnblogs.com/icekx/p/9131618.html
https://blog.csdn.net/weixin_41712499/article/details/85860972
https://blog.csdn.net/zxzxzx0119/article/details/81097546
若节点类型没有parent属性,采用中序遍历方式获取后继节点:
def getSuccessorNode(head, node):
if (not node) or (not head):
return None
stack = []
flag = False
while head or len(stack) > 0:
if head:
stack.append(head)
head = head.left
else:
head = stack.pop()
if flag:
return head
if head == node: # 若找到当前节点,则下一个弹出的节点即为后继节点
flag = True
head = head.right
return None
若节点存在parent属性即:
class TreeNode:
def __init__(self, x=0):
self.val = x
self.parent = None
self.left = None
self.right = None
def getSuccessorNode(node):
if not node :
return None
if node.right: # 如果当前节点有右子树,则返回右子树的最左边节点
node = node.right
while node.left:
node = node.left
return node
else: # 没有右子树 则向上找寻父节点,直到为父节点的左子树,返回父节点,否则返回空
par = node.parent
while not par and par.left != node:
node = par
par = par.parent
return par
实现二叉树前、中、后序以及按层遍历
参考:https://blog.csdn.net/qq_34364995/article/details/80787116
https://www.cnblogs.com/bjwu/p/9284534.html
# -*- coding:utf-8 -*-
'''
用Python实现树,并遍历。
'''
class Node():
def __init__(self, x):
self.val = x
self.left = None
self.right = None
def depth(root):
if root is None:
return 0
else:
return 1 + max(depth(root.left), depth(root.right))
#前序遍历
def pre_order(root):
if root is None:
return
else:
print(root.val)
pre_order(root.left)
pre_order(root.right)
#中序遍历
def mid_order(root):
if root is None:
return
else:
mid_order(root.left)
print(root.val)
mid_order(root.right)
#后序遍历
def post_order(root):
if root is None:
return
else:
post_order(root.left)
post_order(root.right)
print(root.val)
#层次遍历
def level_order(root):
if root is None:
return
q = []
q.append(root)
while q:
current = q.pop(0)
print(current.val)
if current.left != None:
q.append(current.left)
if current.right != None:
q.append(current.right)
#按层次打印
def level_print(root):
if root is None:
return []
p = [root]
results = []
current_level_num = 1
next_level_num = 0
d = []
while p:
current = p.pop(0)
d.append(current.val)
current_level_num -= 1
if current.left:
p.append(current.left)
next_level_num += 1
if current.right:
p.append(current.right)
next_level_num += 1
if current_level_num == 0:
current_level_num = next_level_num
next_level_num = 0
results.append(d)
d = []
return results[::-1]
if __name__ == '__main__':
a = Node(3)
b = Node(9)
c = Node(20)
d = Node('null')
e = Node('null')
f = Node(15)
g = Node(7)
a.left = b
a.right = c
b.left = d
b.right = e
c.left = f
c.right = g
print('深度:%d' % depth(a))
print("前序遍历:")
print(pre_order(a))
print('中序遍历:')
print(mid_order(a))
print('后序遍历:')
print(post_order(a))
level_order(a)
print(level_print(a))
leetcode-98 验证二叉搜索树
题目:https://leetcode-cn.com/problems/validate-binary-search-tree/
参考:https://blog.csdn.net/ma412410029/article/details/80733905
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def isValidBST(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
def inorderTraversal(root):
if root == None:
return []
res = []
res += inorderTraversal(root.left)
res.append(root.val)
res += inorderTraversal(root.right)
return res
res = inorderTraversal(root)
if res != sorted(list(set(res))): return False
return True
leetcode-102 二叉树的层次遍历
https://leetcode-cn.com/problems/binary-tree-level-order-traversal/
参考:https://blog.csdn.net/weixin_40314737/article/details/80942856
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def levelOrder(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
queue = [root]
res = []
if not root:
return []
while queue:
templist = []
templen =len(queue)
for i in range(templen):
temp = queue.pop(0)
templist.append(temp.val)
if temp.left:
queue.append(temp.left)
if temp.right:
queue.append(temp.right)
res.append(templist)
return res
leetcode-107 二叉树的层次遍历 II
https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii/
参考:https://blog.csdn.net/qq_34364995/article/details/80427199
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def levelOrderBottom(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
if not root:
return []
queue = [root]
res = []
while queue:
templist = []
length = len(queue)
for i in range(length):
temp = queue.pop(0)
templist.append(temp.val)
if temp.left:
queue.append(temp.left)
if temp.right:
queue.append(temp.right)
res.append(templist)
return res[::-1]
堆
实现一个小顶堆、大顶堆、优先级队列
参考:https://www.coder4.com/archives/3844
小顶堆
import heapq
import random
class TopkHeap(object):
def __init__(self, k):
self.k = k
self.data = []
def Push(self, elem):
if len(self.data) < self.k:
heapq.heappush(self.data, elem)
else:
topk_small = self.data[0]
if elem > topk_small:
heapq.heapreplace(self.data, elem)
def TopK(self):
return [x for x in reversed([heapq.heappop(self.data) for x in xrange(len(self.data))])]
if __name__ == "__main__":
print "Hello"
list_rand = random.sample(xrange(1000000), 100)
th = TopkHeap(3)
for i in list_rand:
th.Push(i)
print th.TopK()
print sorted(list_rand, reverse=True)[0:3]
大顶堆
class BtmkHeap(object):
def __init__(self, k):
self.k = k
self.data = []
def Push(self, elem):
# Reverse elem to convert to max-heap
elem = -elem
# Using heap algorighem
if len(self.data) < self.k:
heapq.heappush(self.data, elem)
else:
topk_small = self.data[0]
if elem > topk_small:
heapq.heapreplace(self.data, elem)
def BtmK(self):
return sorted([-x for x in self.data])
优先级队列
参考:https://blog.csdn.net/j086924/article/details/82736301
import heapq
class PriorityQueue:
def __init__(self):
self._queue = []
self._index = 0
def push(self, item, priority):
heapq.heappush(self._queue, (-priority, self._index, item))
self._index += 1
def pop(self):
return heapq.heappop(self._queue)[-1]
class Item:
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Item({!r})'.format(self.name)
if __name__ == "__main__":
q = PriorityQueue()
q.push(Item('python'), 1)
q.push(Item('java'), 5)
q.push(Item('swift'), 4)
q.push(Item('c++'), 1)
for i in range(4):
print(q.pop())
实现堆排序
参考:https://www.jianshu.com/p/d174f1862601
from collections import deque
def swap_param(L, i, j):
L[i], L[j] = L[j], L[i]
return L
def heap_adjust(L, start, end):
temp = L[start]
i = start
j = 2 * i
while j <= end:
if (j < end) and (L[j] < L[j + 1]):
j += 1
if temp < L[j]:
L[i] = L[j]
i = j
j = 2 * i
else:
break
L[i] = temp
def heap_sort(L):
L_length = len(L) - 1
first_sort_count = L_length / 2
for i in range(first_sort_count):
heap_adjust(L, first_sort_count - i, L_length)
for i in range(L_length - 1):
L = swap_param(L, 1, L_length - i)
heap_adjust(L, 1, L_length - i - 1)
return [L[i] for i in range(1, len(L))]
def main():
L = deque([50, 16, 30, 10, 60, 90, 2, 80, 70])
L.appendleft(0)
print heap_sort(L)
if __name__ == '__main__':
main()
利用优先级队列合并 K 个有序数组
参考:https://blog.csdn.net/u012328476/article/details/52522900
https://blog.csdn.net/qiuye2014/article/details/86707126
求一组动态数据集合的最大 Top K
参考:https://github.com/wangzheng0822/algo/blob/master/python/28_binary_heap/top_k.py
import random
from heap import MinHeap
def top_k(nums, k):
"""
返回数组的前k大元素
:param nums:
:param k:
:return:
"""
if len(nums) <= k:
return nums
min_h = MinHeap(nums[:k], k)
for i in range(k, len(nums)):
tmp = min_h.get_top()
if nums[i] > tmp:
min_h.remove_top()
min_h.insert(nums[i])
return min_h.get_data()
if __name__ == '__main__':
nums = []
k = 3
for i in range(20):
nums.append(random.randint(1, 100))
print('--- nums ---')
print(nums)
print('--- top {} ---'.format(k))
print(top_k(nums, k))