树的四种分类
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Search trees:实例--二叉搜索树
什么是二叉搜索树
二叉搜索树(Binary Search Tree)是一棵有序的二叉树,所以我们也可以称它为二叉排序树(不知道二叉树的童鞋,先看看二叉树:传送门)。
具有以下性质的二叉树我们称之为二叉搜索树:若它的左子树不为空,那么左子树上的所有值均小于它的根节点;若它的右子树不为空,那么右子树上所有值均大于它的根节点。它的左子树和右子树分别也为二叉搜索树。
2、二叉搜索树的结构
二叉搜索树能够高效的进行一下操作:①插入一个数值②查询是否包含某个数值③删除某个数值
根据实现的不同,还可以实现其他各种操作,这是一种使用性很高的数据结构。我们来看一个例子:
这就是二叉搜索树的存储结构,所有的节点,都满足左子树上的比自己小,而右子树上的所有节点比自己大。二叉搜索树因为其有序性,所以它能够高效的管理数的集合
(1)查询
我们查找是否存在17:
<1>根节点是7,因为小于17,所以去右子树查找
<2>走到节点12,还是小于17,所以继续往右子树找
<3>走到节点17,此时找到17。
(2)插入
我们使用查找的方式进行插入,以数字6为例,如图所示:
(3)删除
删除操作相对之前的其他两种操作,就略显复杂一些。一般来说我们可以分为三种情况:
<1>需要删除的节点没有左儿子,那么就把右儿子提上去
<2>需要删除的节点的左儿子没有右儿子,那么就把左儿子提上去
<3>不满足上述的两种情况的话,就把左子树中最大的节点放到要删除的节点上。
3、二叉搜索树的复杂度
无论我们执行哪一个操作,其所花的时间都和树的高度成正比。我们不难得知,二叉搜索树的平均复杂度为O(log n)。
4、二叉搜索树的实现
通过上述的了解,我们大致已经知道二叉搜索树的工作原理。所以现在我们就来简单的实现二叉搜索树基本的增删查的功能,代码如下:
[cpp]view plain copy
1.//表示节点的结构体
2.struct node{
3.int val;
4.node*lch,*rch;
5.};
6.//插入整数x
7.node*insert(node*p,int x){
8.if(p==NULL){
9.node*newNode=new node;
10.newNode->val=x;
11.newNode->lch=newNode->rch=NULL;
12.p=newNode;
13.}else{
14.if(x
15.else p->rch=insert(p->rch,x);
16.}
17.return p;
18.}
19.//查找整数x
20.bool find(node*p,int x){
21.if(p==NULL)return false;
22.else if(p->val==x)return true;
23.else if(p->val>x)return find(p->lch,x);
24.else return find(p->rch,x);
25.}
26.//删除整数x
27.node*remove(node*p,int x){
28.if(p==NULL)return NULL;
29.else if(x
30.else if(x>p->val)p->rch=remove(p->rch,x);
31.//情况<1>
32.else if(p->lch==NULL){
33.node*q=p->rch;
34.delete p;
35.return q;
36.}
37.//情况<2>
38.else if(p->lch->rch==NULL){
39.node*q=p->lch;
40.q->rch=p->rch;
41.delete p;
42.return q;
43.}
44.//情况<3>
45.else{
46.node*q;
47.for(q=p->lch;q->rch->rch!=NULL;q=q->rch);
48.node*r=q->rch;
49.q->rch=r->lch;
50.r->lch=p->lch;
51.r->rch=p->rch;
52.delete p;
53.return r;
54.}
55.return p;
56.}
Heaps;实例--斐波那契堆
斐波纳契堆(Fibonacci Heap)于1984年由Michael L.Fredman与Robert E.Tarjan 提出,1987年公开发表,名字来源于运行时分析所使用的斐波那契数。
斐波那契堆同二项堆(Binomial Heap)一样,也是一种可合并堆(Mergeable Heap)。与二项堆一样,斐波那契堆是由一组最小堆有序树构成,但堆中的树并不一定是二项树。与二项堆中树都是有序的不同,斐波那契堆中的树都是有根而无序的。
特点:不涉及删除元素的操作有O(1)的平摊时间。Extract-Min和Delete的数目和其它相比较小时效率更佳。关键思想在于尽量延迟对堆的维护
稠密图每次Decrease-key只要O(1)的平摊时间,和二项堆的O(lgn)相比是巨大的改进。
斐波那契堆的结构较二项堆更松散。因此对结构的维护可以到方便时再做。
斐波那契堆中的树是有根而无序的。每个节点包含一个指向其父节点的指针p[x],以及一个指向其任一子女的指针child[x](指向子女双链表)。
每个孩子有left[x]和right[x]。(意义:在O(1)的时间内去掉一个节点,或者在O(1)的时间内合并双链表。)其它域:degree[x]存储子女个数。mark[x]指示自从x上一次成为另一节点的子女以来,它是否失掉一个孩子。
一个给定的斐波那契堆可以通过一个指向其含有最小关键字树的指针来访问。