本文参考 跟波波学数据结构视频
1.什么是树?
- 树是一个无环的,无向连同图
- 有n个节点,和n-1条边
- 有一个根节点,通常需要一个引用
- 任意点条连接,且只有条路径
2.树的相关概念
- 父节点:直接相连的两个节点,上面的叫父节点。
- 子节点:下面的叫子节点。
- 根节点:没有父节点,有的实现中,根节点的父节点,指向自己。
- 叶子节点:没有子节点的节点。
- 子树:包含再一棵树中的小数 用
表示
3.什么是二叉树(bt)
英文 binnary tree 简称BT ,每个节点最多只有两颗数,
4.什么是二叉搜索数
二叉搜索数 ,英文 binnary search tree 简称BST,二叉搜索树,是二叉树且满足BST不变式,对于任意有子树的节点都满足,左子树的值都小于节点的值,右子树的值都大于节点的值。
5.二叉搜索树的用途
- 实现 map或者set这样的抽象数据结构。
- 实现红黑树
- 实现平衡二叉搜索树
- 伸展树 。。。
- 实现堆~二叉堆
- 构建语法树
- 树堆(treap)~ 一种概率数据结构
6.BST的操作和复杂度
操作 | 平均情况 | 最坏情况 |
插入insert | O(logn) | O(n) |
删除delete | O(logn) | O(n) |
移除remove | O(logn) | O(n) |
搜索search | O(logn) | O(n) |
7.动画演示
(1)添加元素,跟波波学数据结构_插入
(2)移除元素,跟波波学数据结构_搜索和删除
8.二叉树的遍历(先序遍历、中序遍历、后续遍历、层遍历)
(1)伪代码
//先序遍历
preorder(node):
if node == null: return
print(node.value) //先序遍历再递归前打印输出
preorder(node.left)
preorder(node.right)
//中序遍历
inorder(node):
inorder(node.left)
if node == null: return
print(node.value) //中序遍历再递归中间打印输出
inorder(node.right)
//中序遍历
postorder(node):
inoder(node.left)
inoder(node.right)
if node == null: return
print(node.value) //后序遍历再递归后打印输出
/**非递归方式实现 **/
//先序遍历
Let Q be Queue
Q.enqueue(rootNode)
while Q is not empty:
node = Q.dequeue()
node.visited = true
if node.right is not null:
Q.enqueue(node.right)
if node.left is not null:
Q.enqueue(node.left)
// 中序遍历
Let Q be Queue
Q.enqueue(rootNode)
while Q is not emtpy:
trav = Q.top() //如果栈没有top()操作 需要每次入栈时记录,把入栈元素赋值给变量trav
if trav.left is not null:
Q.enqueue(trav.left)
else:
node = Q.dequeue()
node.visited = true
if node.right is not null:
Q.enqueue(node.right)
//后续遍历
Let Q1 be a Queue
Let Q2 be a Queue
Q1.enqueue(rootNode)
while Q1 is not null:
node = Q1.dequeue()
Q2.enqueue(node)
if node.left is not null:
Q1.enqueue(node.left)
if node.right is not null:
Q1.enqueue(node.right)
while Q2 is not null:
node = Q2.dequeue()
node.visited
(2)二叉树,经过三种遍历后,会得到三个线性的串。
(3)已知中序遍历和另外一个可以求第三个。也可以反推树的结构。
下面我们模拟根据前序遍历和中序遍历构建二叉树的过程:
我们已经知道:前序遍历按照先访问根,再访问子节点的顺序进行遍历;中序遍历则按照先访问左子树,再访问根,再访问右子树的顺序进行遍历,那么我们可以确定一个恢复树结构的思路:
- 首先根据先序遍历开头确定根节点A:第一个节点一定是根节点
- 根据中序遍历的性质,从A进行分割,将整棵二叉树划分为左子树和右子树,左子树中序遍历BCDE;右子树中序遍历GHFI
- 根据左子树下后序遍历分割先序遍历,左子树先序遍历BCDE;右子树先序遍历FGHI
- 重复做前面的过程,根据先序遍历确定当前层的根节点,再分割树,直至中序遍历只剩一个节点为止停止递归
(4)二叉搜索树的中序遍历,元素是按照从小到大顺序输出的。
(5)层次遍历,使用宽度优先搜索(DFS)
为了实现宽度优先搜索(BFS),我们需要维护一个queue,其中记录剩下的需要遍历的节点。
队列重点节点先从根节点开始,一直队列为空。
伪代码如下:
let Q be a Queue Q.EnQueue(root_node) while Q is not empty : current := queue.Dequeue() current.visited if current has child : for child in current.children: Q.EnQueue(child)
遍历过程可参考 跟波波学数据结构_树的遍历 9分钟处
9.二叉搜索树的go语言实现。