二叉查找树
二叉查找树的API设计
put方法的实现思想:
public class BinaryTree<Key extends Comparable<Key>, Value> {
private Node root;
private int N;
public int size(){
return N;
}
public void put(Key key, Value value){
root = put(root,key,value);
}
public Node put(Node x, Key key, Value value){
// 如果node为空
if (x == null){
N++;
return new Node(key,value,null,null);
}
// 如果node不为空
// 比较值大小,并添加对应的节点
int cmp = key.compareTo(x.key);
if (cmp > 0){
// 如果key大于x节点的键,则继续找x节点的右子树
x.right = put(x.right,key, value);
}else if (cmp < 0){
// 如果key小于x节点的键,则继续找x节点的左子树
x.left = put(x.left,key, value);
}else {
// 如果key等于x节点的键,则修改x节点的value
x.value = value;
}
return x;
}
public Value get(Key key){
return get(root,key);
}
public Value get(Node x, Key key){
// x节点为null
if (x == null){
return null;
}
Value value;
// x节点不为null
// 比较键大小,找到对应元素
int cmp = key.compareTo(x.key);
if (cmp > 0){
// 如果key大于x节点的键,则继续找x节点的右子树
value = get(x.right, key);
}else if (cmp < 0){
// 如果key小于x节点的键,则继续找x节点的左子树
value = get(x.left, key);
}else {
// 如果key等于x节点的键,则取x节点的value
value = x.value;
}
return value;
}
public void delete(Key key){
delete(root,key);
}
public Node delete(Node x, Key key){
// x节点为null
if (x == null){
return null;
}
// x节点不为null
// 比较键大小,找到对应元素
int cmp = key.compareTo(x.key);
if (cmp > 0){
// 如果key大于x节点的键,则继续找x节点的右子树
x.right = delete(x.right, key);
}else if (cmp < 0){
// 如果key小于x节点的键,则继续找x节点的左子树
x.left = delete(x.left, key);
}else {
N--;
// 如果key等于x节点的键,则删除x节点
// 找到右子树中的最小节点
if (x.right == null){
return x.left;
}
if (x.left == null){
return x.right;
}
Node minNode = x.right;
while (minNode.left != null){
minNode = minNode.left;
}
// 删除右子树中最小的节点
Node n = x.right;
while (n.left != null){
if (n.left.left == null){
n.left = null;
}else {
n = n.left;
}
}
// 让x节点左子树为minNode的左子树
// 让x节点右子树为minNode的右子树
minNode.left = x.left;
minNode.right = x.right;
// 让x节点的父节点指向minNode
x = minNode;
}
return x;
}
public Key min(){
return min(root).key;
}
public Node min(Node x){
if (x.left != null){
return min(x.left);
}else{
return x;
}
}
private class Node{
public Key key;
public Value value;
public Node left;
public Node right;
public Node(Key key, Value value, Node left, Node right) {
this.key = key;
this.value = value;
this.left = left;
this.right = right;
}
}
}
时间复杂度为O(X^2):----深度优先
// 前序遍历
public Queue<Key> preErgodic(){
Queue<Key> keys = new Queue<>();
preErgodic(root,keys);
return keys;
}
public void preErgodic(Node x, Queue<Key> keys){
if (x == null)return;
// 把x节点的key放入集合中
keys.enqueue(x.key);
// 递归遍历x节点的左子树
if (x.left != null){
preErgodic(x.left, keys);
}
// 递归遍历x节点的右子树
if (x.right != null){
preErgodic(x.right, keys);
}
}
层序遍历----广度优先
求树的最大深度
折纸问题
堆---完全二叉树
堆的数据结构属于完全二叉树,底层可以通过数组实现,0索引位置不放元素,如果一个节点位置为k,则两个子节点分别为2k和2k+1,且父节点值大于两个子节点值,两个子节点大小没有顺序.
最大优先队列的底层原理和堆是一样的.
索引优先队列
2-3查找树----平衡树
红黑树
红黑树保持平衡的机制
左旋
右旋
B树
B+树
数据库中创建索引的数据结构就是B+树
并查集
public class UF {
// 记录节点元素和该元素所在节点的标识
private int[] eleAndGroup;
// 记录并查集中数据的分组个数
private int count;
public UF(int N) {
this.count = N;
this.eleAndGroup = new int[N];
for (int i = 0; i < this.eleAndGroup.length; i++) {
this.eleAndGroup[i] = i;
}
}
// 获取当前并查集中数据分组的个数
public int count(){
return count;
}
// 获取p元素所在组的标识符
public int find(int p){
return eleAndGroup[p];
}
// 查询p和q是否属于同一分组
public boolean connected(int p, int q){
return find(p) == find(q);
}
// 合并p和q所在分组
public void union(int p, int q){
if (connected(p,q)){
return;
}
int pGroup = find(p);
int qGroup = find(q);
for (int i = 0; i < eleAndGroup.length; i++) {
if (eleAndGroup[i] == pGroup){
eleAndGroup[i] = qGroup;
}
}
count--;
}
}