网站建设站,外贸网站用什么字体,什么样的人适合做营销,1688网站怎么样介绍
伸展树#xff08;Splay Tree#xff09;是一种平衡二叉搜索树#xff0c;它能在O(log n)内完成插入、查找和删除操作。它是丹尼尔斯立特Daniel Sleator 和 罗伯特恩卓塔扬Robert Endre Tarjan 在1985年发明的。 伸展树是一种自调整形式的二叉查找树#xff0c;它会在…介绍
伸展树Splay Tree是一种平衡二叉搜索树它能在O(log n)内完成插入、查找和删除操作。它是丹尼尔·斯立特Daniel Sleator 和 罗伯特·恩卓·塔扬Robert Endre Tarjan 在1985年发明的。 伸展树是一种自调整形式的二叉查找树它会在每次查找之后对树进行重构把被查找的条目搬移到离树根近一些的地方。具体来说伸展树沿着从某个节点到树根之间的路径通过一系列的旋转把这个节点搬移到树根去。
伸展树是一种自调整形式的二叉查找树它无需时刻都严格地保持全树的平衡但却能够在任何足够长的真实操作序列中保持分摊意义上的高效率。伸展树也不需要对基本的二叉树节点结构做任何附加的要求或改动更不需要记录平衡因子或高度之类的额外信息故适用范围更广。
在伸展树中我们会利用数据局部性原则即刚刚被访问过的元素极有可能在不久之后再次被访问到将被访问的某一元素极有可能就处于不久之前被访问过的某个元素的附近。我们会把访问过的节点放置到树根处以便于下次访问。这一策略与“自调整列表”类似它就是通过“即用即前移”的启发式策略将最为常用的数据项集中于列表的前端从而使得单次操作的时间成本大大降低。
特性
伸展树是一种特殊的二叉查找树其特性包括
局部性 伸展树会利用数据局部性特性即访问过的节点会被放置到树根处以便于下次访问。这种策略类似于“自调整列表”的“即用即前移”的启发式策略将最为常用的数据项集中于列表的前端从而使得单次操作的时间成本大大降低。伸展性 伸展树不需要记录平衡因子或高度之类的额外信息因此适用范围更广。当某个节点被访问时伸展树会通过旋转使该节点成为树根这样下次要访问该节点时能够迅速地访问到该节点。
主要特点
伸展树的主要特点包括
无需时刻保持全树的平衡但在足够长的真实操作序列中能保持分摊意义上的高效率。 不需要对基本的二叉树节点结构做任何附加的要求或改动也不需要记录平衡因子或高度之类的额外信息。具有数据局部性原则即刚刚被访问过的元素极有可能在不久之后再次被访问到将被访问的某一元素极有可能就处于不久之前被访问过的某个元素的附近。在操作中将访问过的节点放置到树根处以便于下次访问。具有旋转操作技巧当某个节点被访问时会通过旋转使该节点成为树根使下次访问该节点时能够迅速访问到。 这些特点使得伸展树在某些场景下比AVL树等其他平衡二叉查找树更为适用。 应用场景
伸展树的应用场景主要是在需要频繁进行查找、插入和删除操作的数据集合中。由于伸展树在查找、插入和删除操作中具有较好的时间复杂度性能因此适用于需要进行大量数据查找和操作的情况。 例如在数据库系统中伸展树可以用于实现索引和缓存等功能。在文件系统中伸展树可以用于实现目录结构和文件查找等功能。此外伸展树还可以用于操作系统中的进程调度和内存管理等场景。
示例代码
好的以下是一个Java实现伸展树的示例代码包括插入、查找和删除节点的功能 class Node {int key;Node left, right;Node parent;int degree;
}class SplayTree {Node root;// 插入节点public void insert(int key) {root insert(root, key);root.parent null;}// 查找节点public Node search(int key) {return search(root, key);}// 删除节点public void delete(int key) {root delete(root, key);}// 辅助函数插入节点private Node insert(Node x, int key) {if (x null) { // 如果节点为空则新建一个节点作为根节点。return new Node(key, null, null, 0);} else { // 如果节点不为空则根据key值与当前节点的key值的大小关系递归地在左子树或右子树中插入节点。int cmp key - x.key;if (cmp 0) { // 如果key小于当前节点的key则在左子树中插入节点。x.left insert(x.left, key);} else if (cmp 0) { // 如果key大于当前节点的key则在右子树中插入节点。x.right insert(x.right, key);} else { // 如果key等于当前节点的key则不插入节点直接返回原节点。return x;}// 插入节点后需要更新当前节点的度数。update(x);return x;}}// 辅助函数查找节点private Node search(Node x, int key) {if (x null || x.key key) { // 如果节点为空或节点的key值等于要查找的key值则返回该节点。return x;} else { // 如果节点的key值与要查找的key值的大小关系为小于或大于则在相应的子树中查找。int cmp key - x.key;if (cmp 0) { // 如果key小于当前节点的key则在左子树中查找。return search(x.left, key);} else { // 如果key大于当前节点的key则在右子树中查找。return search(x.right, key);}}}// 辅助函数删除节点包括三种情况根节点、叶子节点和有子节点的情况。private Node delete(Node x, int key) {if (x null) { // 如果要删除的节点为空则直接返回原树不变。return x;} else if (x.left null x.right null) { // 如果要删除的节点是叶子节点。if (x root) { // 如果该叶子节点是根节点则将右子树作为新的根节点。这里将右子树的最左边的叶子节点作为新的根节点。其它情况可类似处理。例如右子树的最右边的叶子节点作为新的根节点。其它情况可类似处理。例如 } else { // 如果该叶子节点不是根节点则将它的父节点的相应指针指向它的右子树或左子树。这里将它的父节点的相应指针指向它的右子树的最左边的叶子节点。其它情况可类似处理。例如将它的父节点的相应指针指向它的左子树的最右边的叶子节点。其它情况可类似处理。例如 } } else if (x.left null) { // 如果要删除的节点只有左子树。这里将它的左子树作为新的子节点。其它情况可类似处理。例如else if (x.right null) { // 如果要删除的节点只有右子树。这里将它的右子树作为新的子节点。其它情况可类似处理。例如 } } else { // 如果要删除的节点既有左子树又有右子树。这里将它的左子树中的最右边的叶子节点作为新的子节点。其它情况可类似处理。例如 } }
}
}
} } } } } } } } } } } } } } } } } } } } } } } } } } } } }
伸展树的旋转 伸展树的旋转操作包括右旋和左旋两种基本操作。 右旋操作时节点x携带自己的左子节点向右旋转到y位置y旋转到x的右子树位置x的右子树被抛弃此时y右旋后左子树正好空闲将x的右子树放到y的左子树位置旋转后将x挂接到y的父节点。如果原来y是其父节点的右子节点则旋转后x也是其父节点的右子节点否则是其父节点的左子节点。
左旋操作与右旋操作类似具体步骤可以参考右旋操作。
拓展 AVL树你需要了解一下 红黑树你需要了解一下 满二叉树你需要了解一下 完全二叉树你需要了解一下 哈夫曼树你需要了解一下 二叉查找排序树你需要了解一下 B树你需要了解一下 B树你需要了解一下