伸展树

伸展树结合了二叉搜索树BST及二叉平衡树AVL的旋转特点,在每一次访问到某节点时都通过旋转将该节点往上推一位,由于没有保存高度信息因为空间复杂度稍优于二叉平衡树。伸展树的插入,删除,搜索的平均时间复杂度均为o(logn),极端情况下为o(n)。伸展树适用于关注用户习惯性行为,用户经常使用的节点将靠近根节点,而用户不经常使用的将远离根节点。

具体实现代码为:

与BST树实现代码一样,如果伸展树遇到不平衡的情况下,代码中的递归调用将会溢出。

  1 template<typename T>
  2 struct splay_tree_node
  3 {
  4     splay_tree_node(const T& _element, splay_tree_node *_left = NULL, splay_tree_node *_right = NULL, bool _isdeleted = false)
  5         : element(_element)
  6         , left(_left)
  7         , right(_right)
  8         , isdeleted(_isdeleted)
  9     {
 10     }
 11     T    element;
 12     splay_tree_node    *left;
 13     splay_tree_node    *right;
 14     bool isdeleted;
 15 };
 16 
 17 template<typename T>
 18 class splay_tree
 19 {
 20     typedef splay_tree_node<T> tree_node;
 21 public:
 22     splay_tree() { m_root = NULL; }
 23     splay_tree(const splay_tree& rhs)
 24         : m_root(clone(rhs.m_root))
 25     {}
 26     const splay_tree& operator=(const splay_tree& rhs)
 27     {
 28         if(this!=&rhs)
 29         {
 30             clear();
 31             m_root = clone(rhs.m_root);
 32         }
 33     }
 34 
 35     ~splay_tree() 
 36     {
 37         clear(m_root);
 38     }
 39 
 40 public:
 41     // 最小值
 42     const T& min() const
 43     {
 44         tree_node* node = min(m_root);
 45         if(node)
 46         {
 47             return node->element;
 48         }
 49         throw std::runtime_error("查找二叉树无任何节点");
 50     }
 51 
 52     // 最大值
 53     const T& max() const
 54     {
 55         tree_node* node = max(m_root);
 56         if(node)
 57         {
 58             return node->element;
 59         }
 60         throw std::runtime_error("查找二叉树无任何节点");
 61     }
 62 
 63     // 判断树上是否包含该值
 64     bool contains(const T& x)
 65     {
 66         bool brotate = false;
 67         return contains(x,m_root,brotate);
 68     }
 69 
 70     // 判断树是否为空
 71     bool is_empty() const
 72     {
 73         return m_root==NULL;
 74     }
 75 
 76     // 清空树
 77     void clear()
 78     {
 79         clear(m_root);
 80     }
 81 
 82     // 插入值为x的节点
 83     void insert(const T& x)
 84     {
 85         insert(x,m_root);
 86     }
 87 
 88     // 移除值为x的节点
 89     void remove(const T& x)
 90     {
 91         remove(x,m_root);
 92     }
 93 
 94     // 对所有节点执行某项动作
 95     template<typename Functor>
 96     void foreach(Functor& functor)
 97     {
 98         foreach(m_root,functor);
 99     }
100 
101 private:
102     // 树最小节点
103     tree_node* min(tree_node* t) const
104     {
105         if( t==NULL )
106         {
107             return NULL;
108         }
109         while(t->left!=NULL)
110         {
111             t = t->left;
112         }
113         return t;
114     }
115 
116     // 树最大节点
117     tree_node* max(tree_node* t) const
118     {
119         if( t==NULL )
120         {
121             return NULL;
122         }
123         while(t->right!=NULL)
124         {
125             t = t->right;
126         }
127         return t;
128     }
129 
130     // 判断树是否存在该节点
131     bool contains(const T& x, tree_node*& t, bool& brotate)
132     {
133         if( t == NULL )
134         {
135             return false;
136         }
137         else if( x<t->element )
138         {
139             if(contains( x, t->left, brotate ))
140             {
141                 if(!brotate)
142                 {
143                     rotate_single_left(t);
144                     brotate = true;
145                 }
146                 return true;
147             }
148             else
149             {
150                 return false;
151             }
152         }
153         else if( x>t->element )
154         {
155             if(contains(x, t->right, brotate))
156             {
157                 if(!brotate)
158                 {
159                     rotate_single_right(t);
160                     brotate = true;
161                 }
162                 return true;
163             }
164             else
165             {
166                 return false;
167             }
168         }
169         else
170         {
171             if(!t->isdeleted)
172             {
173                 return true;
174             }
175             else
176             {
177                 return false;
178             }
179         }
180     }
181 
182     // 插入节点
183     void insert(const T& x, tree_node*& t)
184     {
185         if( t == NULL )
186         {
187             t = new tree_node(x,NULL,NULL);
188         }
189         else if( x<t->element)
190         {
191             insert(x,t->left);
192         }
193         else if( x>t->element )
194         {
195             insert(x,t->right);
196         }
197         else
198         {
199             if(t->isdeleted)
200             {
201                 t->isdeleted = false;
202             }
203         }
204     }
205 
206     // 移除某节点
207     void remove(const T& x, tree_node*& t)
208     {
209         if( t== NULL )
210         {
211             return;
212         }
213         else if( x < t->element)
214         {
215             remove(x,t->left);
216         }
217         else if( x > t->element )
218         {
219             remove(x,t->right);
220         }
221         else if( t->left != NULL && t->right != NULL)
222         {
223             //t->element = min( t->right )->element;
224             //remove( t->element, t->right);
225             t->isdeleted = true;
226         }
227         else
228         {
229             //splay_tree_node *old_node = t;
230             //t = (t->left != NULL)?t->left:t->right;
231             //delete old_node;
232             t->isdeleted = true;
233         }
234     }
235 
236     // 清除该节点为根节点的树
237     void clear(tree_node*& t)
238     {
239         if(t != NULL)
240         {
241             clear(t->left);
242             clear(t->right);
243             delete t;
244             t = NULL;
245         }
246     }
247 
248     // 对该节点的为根节点的树的所有子节点执行某项动作
249     template<typename Functor>
250     void foreach(tree_node* t, Functor& functor)
251     {
252         if(t!=NULL)
253         {
254             functor(t);
255             foreach(t->left, functor);
256             foreach(t->right, functor);
257         }
258     }
259 
260     // 深拷贝树
261     tree_node* clone(tree_node* t) const
262     {
263         if( t==NULL )
264         {
265             return NULL;
266         }
267         return new tree_node(t->element, clone(t->left), clone(t->right));
268     }
269 
270     // 单旋转-LL
271     void rotate_single_left(tree_node*& k2)
272     {
273         tree_node* k1 = k2->left;
274         k2->left = k1->right;
275         k1->right = k2;
276         k2 = k1;
277     }
278 
279     // 单旋转-RR
280     void rotate_single_right(tree_node*& k2)
281     {
282         tree_node* k1 = k2->right;
283         k2->right = k1->left;
284         k1->left = k2;
285         k2 = k1;
286     }
287 
288 private:
289     tree_node    *m_root;
290 };

转载于:https://www.cnblogs.com/liumu1209/archive/2012/10/02/2710355.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/361217.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS属性选择器温故-4

1.属性选择器就是通过元素属性来找到元素 2.属性选择器语法 CSS3遵循了惯用的编码规则&#xff0c;通配符的使用提高了样式表的书写效率&#xff0c;也使CSS3的属性选择器更符合编码习惯 3.浏览器兼容性 CSS选择器总结&#xff1a;CSS选择器和jQuery的选择器非常相似&#xff…

如何封装Spring bean

据我所知&#xff0c;Spring Framework除了具有单独的上下文之外&#xff0c;没有提供任何封装Spring bean的机制。 因此&#xff0c;当您在Spring的Inversion of Control容器中注册了公共类时&#xff0c;可以通过相同的上下文配置将其自动连接到任何Spring bean中。 这非常强…

分享下自己的EmpireofCode进攻策略 https://empireofcode.com/ https://empireofcode.com/game/#

# 没什么用&#xff0c;该游戏的模块调用不友好&#xff0c;取数据难import queue from battle import commander # import mathunit_client commander.Client() doing_last_order True towerid [] towerrg [] towerfr [] towerps [] tower_id 0 towers [] safe_posi[4…

Python多篇新闻自动采集

昨天用python写了一个天气预报采集&#xff0c;今天趁着兴头写个新闻采集的。 目标是&#xff0c;将腾讯新闻主页上所有新闻爬取下来&#xff0c;获得每一篇新闻的名称、时间、来源以及正文。 接下来分解目标&#xff0c;一步一步地做。 步骤1&#xff1a;将主页上所有链接爬取…

使用ADF BC管理保存点

在使用ADF BC时&#xff0c;我们通常依赖于在数据库中执行DML操作的框架。 在DBTransaction提交周期内&#xff0c;该框架正确地在数据库中进行了所有必要的更新。 很酷的事情是&#xff0c;在这种情况下&#xff0c;数据库事务将被自动管理。 因此&#xff0c;如果出现问题&am…

sql优化(转)

(转)SQL 优化原则一、问题的提出 在应用系统开发初期&#xff0c;由于开发数据库数据比较少&#xff0c;对于查询SQL语句&#xff0c;复杂视图的的编写等体会不出SQL语句各种写法的性能优劣&#xff0c;但是如果将应用 系统提交实际应用后&#xff0c;随着数据库中数据的增加&a…

2017-12-04HTML table布局

<!DOCTYPE html> <html> <head lang"en"> <meta charset"UTF-8"> <title>table布局</title> </head> <body marginwidth"0px" marginheight"0px"> <table width"…

Java EE 8发生了什么? (第2部分)

Java EE 8的工作仍处于初期阶段&#xff0c;预计在来年会紧跟潮流&#xff0c;我们将看到专家组的形成完成&#xff0c;围绕用例/功能的更多讨论&#xff0c;许多JIRA&#xff0c;以及各种规范的草案版本&#xff08;本会很有趣&#xff01;&#xff09;。 在第1部分中 &#…

foreach语句的的解析

我这个虾米&#xff0c;今天才知道foreach语句是这样解析的&#xff0c;惭愧啊&#xff01;幸好我最新在原生态的学习这门编程语言。 //程序中我们这样写foreachforeach (Person item in Persons){Console.WriteLine(item);} //其实如果要使用foreach,需要实现IEnumerator接口&…

滚动条位置判断

//获取滚动条距离顶部位置function getScrollTop() { var scrollTop 0; if (document.documentElement && document.documentElement.scrollTop) { scrollTop document.documentElement.scrollTop; } else if (document.body) { scrollTop d…

如何处理Java注释

Java 8的很酷的新功能之一就是对lambda表达式的支持。 Lambda表达式在很大程度上依赖于FunctionalInterface 注释 。 在本文中&#xff0c;我们将介绍注释以及如何处理它们&#xff0c;以便您可以实现自己的出色功能。 注解 Java 5中添加了注释 。Java语言附带了一些预定义的…

(转)MFC技巧学习五

51. 如何获得其他程序的图标,并显示在View中 [问题提出] 有的时候,如:类资源管理器会遇到获得程序图标并显示的操作,如何实现呢? [解决方法] SDK函数SHGetFileInfo来获得有关文件的很多信息:如大小图标,属性,类型等.  [程序实现] 建立名为My的SDI工程.在OnPaint()函数中…

使用navicat premium将数据库从Oracle迁移到SQL Server,或从Oracle迁移到MySQL

有时候我们有迁移数据库的需求&#xff0c;例如从Oracle迁移到SQL Server&#xff0c;或者从MySQL迁移到Oracle。 很多江湖好汉一时不知如何手工操作&#xff0c;所幸的是Navicat提供了迁移的自动化操作界面。 当然&#xff0c;Navicat的数据库迁移无法做到完美&#xff0c;一些…

书评:Mockito Essentials

Sujoy Acharya的Mockito Essentials副标题&#xff08; Packt Publishing &#xff0c;2014年10月&#xff09;是&#xff1a;“实用指南&#xff0c;可帮助您使用Mockito进行单元测试并开始运行。” Mockito Essentials中的前言和七章涵盖大约190个实质性页面。 前言 在序言中…

Oracle ORA-07445 [evaopn3()+384] 错误 分析

1.OS 和 DB 版本Oracle Version&#xff1a; 11.2.0.2Operation System&#xff1a;HP-UXItanium 11.312.Alert log中信息Tue Oct 16 22:27:31 2012Exception [type: SIGSEGV,Address not mapped to object] [ADDR:0xC00000000] [PC:0x400000000631B880,evaopn3()384] [flags: …

http网站转换成https网站

https&#xff0c;https的本地测试环境搭建,asp.net结合https的代码实现,http网站转换成https网站之后遇到的问题 一&#xff1a;什么是https SSL&#xff08;Security Socket Layer&#xff09;全称是加密套接字协议层&#xff0c;它位于HTTP协议层和TCP协议层之间&#x…

EAGER的获取是代码的味道

介绍 休眠获取策略确实可以使几乎没有爬网的应用程序和响应速度很快的应用程序有所不同。 在这篇文章中&#xff0c;我将解释为什么您应该选择基于查询的获取而不是全局获取计划。 取得101 Hibernate定义了四种关联检索策略 &#xff1a; 提取策略 描述 加入 原始SELECT语…

基于S2SH的电子商务网站系统性能优化

对于经常逛网页的人来说最受不了的事情就是访问的网页加载太慢&#xff0c;除去网络的原因网站的系统性能对加载的快慢非常重要&#xff0c; 网上有个统计&#xff1a; 每慢500ms Google访问量降低20% 每慢400ms Yahoo 访问量降低5-9% 每慢100ms Amazon销售额降低1% 对于商务网…

玩Java并发

最近&#xff0c;我需要将一些文件&#xff08;每个文件都有JSON格式的对象列表&#xff08;数组&#xff09;&#xff09;转换为每个文件都具有相同数据&#xff08;对象&#xff09;的分隔行的文件。 这是一次性的任务&#xff0c;很简单。 我使用Java nio的某些功能进行了读…

ExtJs的Reader

ExtJs的Reader Reader : 主要用于将proxy数据代理读取的数据按照不同的规则进行解析,讲解析好的数据保存到Modle中 结构图 Ext.data.reader.Reader 读取器的根类 Ext.data.reader.Json JSON格式的读取器 Ext.data.reader.Array 扩展JSON的Array读取器 Ext.data.reader.Xml XML格…