小白专场:是否同一棵二叉搜索树(1)

合集下载

搜索树

搜索树

9/10/2012
30
9/10/2012
31
9/10/2012
32
高度不平衡的二叉搜索树 高度平衡的二叉搜索树
9/10/2012
33
平衡


当确定搜索树的高度总是O(logn)时, 能够保证每个搜索树操作所占用的时 间为O(logn)。 高度为O(logn)的树称为平衡树 (balanced tree)。
根据AVL树的定义,任一结点的平衡因子 只能取 -1,0和 1。 如果一个结点的平衡因子的绝对值大于1, 则这棵二叉搜索树就失去了平衡,不再 是AVL树。
如果一棵二叉搜索树是高度平衡的,它就 成为 AVL树。如果它有 n 个结点,其高 度可保持在O(log2n),平均搜索长度也可 保持在O(log2n)。
二叉搜索树的插入
插入新结点88 每次结点的插入,都要从根结点出发搜索插 入位置,然后把新结点作为叶结点插入。
9/10/2012 14
二叉搜索树的插入
9/10/2012
15
输入数据,建立二叉搜索树的过程
输入数据序列 { 53, 78, 65, 17, 87, 09, 81, 45, 23 }
9/10/2012
22
9/10/2012
9/10/2012
23
二叉搜索树的删除


如果p有两个非空子树。 只需将该元素替换为它的左子树中的 最大元素或右子树中的最小元素。
9/10/2012
249/10/201225二叉搜索树的删除


注意,必须确保右子树中的最小元素以及 左子树中的最大元素或者在没有子树的节 点中,或者在只有一个子树的节点中。 可以按下述方法来查找到左子树中的最大 元素:首先移动到子树的根,然后沿着各 节点的右孩子指针移动,直到右孩子指针 为0为止。 类似地,也可以找到右子树中的最小元素: 首先移动到子树的根,然后沿着各节点的 左孩子指针移动,直到左孩子指针为0为止。

AVL树自平衡的二叉搜索树

AVL树自平衡的二叉搜索树

AVL树自平衡的二叉搜索树AVL树是一种自平衡的二叉搜索树,它是根据其发明者 G.M. Adelson-Velsky 和 Evgenii Landis 的姓氏首字母而得名。

AVL树解决了传统二叉搜索树由于插入或删除操作导致树结构不平衡而引发的性能问题。

1. 什么是二叉搜索树?二叉搜索树,又称二叉排序树或二叉查找树,是一种特殊的二叉树结构。

在二叉搜索树中,每个节点都包含一个键值,并且节点的左子树中的键值小于节点的键值,右子树中的键值大于节点的键值。

2. 为什么需要自平衡?传统的二叉搜索树在执行插入或删除操作时,可能会导致树结构不平衡,使得树的高度远大于理想情况下的最小高度。

当树的高度增加后,查找、插入、删除等操作的时间复杂度也会增加,进而影响整体性能。

3. AVL树的自平衡特性AVL树通过保持树的平衡性来提高性能。

对于每一个节点,AVL 树通过计算其左右子树的高度差(平衡因子)来判断是否需要进行旋转操作来保持树的平衡。

当平衡因子超过一定阈值时,进行相应的旋转操作来维持平衡。

4. AVL树的旋转操作AVL树的旋转操作包括左旋和右旋。

左旋操作将当前节点的右子树变为新的根节点,而右旋操作则恰恰相反。

通过旋转操作,AVL树可以在保持二叉搜索树性质的同时,实现树的自平衡。

5. AVL树的插入操作在进行插入操作时,AVL树首先按照二叉搜索树的规则找到插入位置,并插入新的节点。

然后,从插入节点开始沿着路径向上逐层检查平衡因子,若遇到不平衡的节点,执行相应的旋转操作来恢复树的平衡。

6. AVL树的删除操作在进行删除操作时,AVL树首先按照二叉搜索树的规则找到待删除的节点,并执行删除操作。

然后,从删除节点的父节点开始沿着路径向上逐层检查平衡因子,若遇到不平衡的节点,执行相应的旋转操作来恢复树的平衡。

7. AVL树的平衡性保证AVL树的自平衡操作保证了树的高度始终保持在理想情况下的最小高度的常数倍。

通过对平衡因子的检查并执行旋转操作,AVL树能够有效地保持树的平衡性,使得查找、插入、删除等操作能够在较快的时间内完成。

二叉搜索树C语言探讨与实现

二叉搜索树C语言探讨与实现

二叉搜索树的详解所谓二叉搜索树,就是指对包括树本身的任何一棵子树,左子树的值要小于根节点,右子树的值要大于根节点。

以便在搜索的时候能够从根节点开始一直往下检索。

在搜索树构造合理的情况下复杂度是。

这里主要介绍二叉搜索树的创建和查询以及增加节点和删除节点。

先定义节点的结构体:为了索引更加方便,定义了父节点。

二叉搜索树的创建二叉搜索树的显示二叉搜索树的插入二叉搜索树的删除完整代码:链接:密码:二叉搜索树的创建二叉搜索树的创建分为直接创建和随机创建。

所谓直接创建,就是拿到一系列树以后,根据原有数据的顺序依次以增加节点的方式扩展原二叉搜索树。

而随机创建就是指创建二叉树的过程随机的从给定树种随机选取一个点加入二叉搜索树。

先来介绍直接创建的办法:先创建根节点判空寻找下一个节点插入的位置这里有两点要注意的:是用来表示往下后的父节点。

新节点要插入的位置的父节点,它一定不会是有两个孩子的节点。

如果比插入点的值要大,则父节点一定没有左孩子;如果比插入点的值要小,则没有右孩子。

插入节点直接创建的整个函数为:二叉树的查找这里要注意的是,我们认为在二叉查找数中的关键字是没有重复,如果有重复的只会查找到其中一个,而无法保证返回所有的值。

用递归的方法是最简单的方法:如果为空,或者找到关键词搜索左子树搜索右子树二叉树的显示(层次遍历)二叉树的层次遍历现在主要事采用队列的方法来处理:队列的原理性的内容随便百度都有,这里直接上源码值得注意的是,虽然我们定义的节点是带有父节点的内容,但是实际上我们的遍历算法并没有用到父节点,具有一般适应性。

记录层数初始化遍历过程判断是否还有节点判断和上一个节点是不是同一层,如果不是则分行将节点加入暂存数组并记录层数在这里,效果如下所示642578二叉树的插入二叉树的删除只有右子树只有左子树寻找代替节点的节点,右子树的最小节点即可代替如果即将代替的节点,如果恰好不是的子节点处理节点挪走后的续接问题,值得注意的是由于节点是右子树的最小节点,所以节点不会有左子树。

程序员面试题精选100题

程序员面试题精选100题
思路二对应的代码:
///////////////////////////////////////////////////////////////////// // // Covert a sub binary-search-tree into a sorted double-linked list // Input: pNode // // void ConvertNode(BSTreeNode* pNode, BSTreeNode*& pLastNodeInList) { if(pNode == NULL) return; BSTreeNode *pCurrent = pNode; the head of the sub tree pLastNodeInList - the tail of the double-linked list
if(asRight) { while(pTemp->m_pLeft) pTemp = pTemp->m_pLeft; } // If the current node is the left child of its parent, // return the greatest node in the tree whose root is the current node else { while(pTemp->m_pRight) pTemp = pTemp->m_pRight; } return pTemp; } ///////////////////////////////////////////////////////////////////// // // Covert a binary search tree into a sorted double-linked list // Input: the head of tree // Output: the head of sorted double-linked list ///////////////////////////////////////////////////////////////////// // BSTreeNode* Convert(BSTreeNode* pHeadOfTree) { // As we want to return the head of the sorted double-linked list, // we set the second parameter to be true return ConvertNode(pHeadOfTree, true); }

二叉树常见面试题(进阶)

二叉树常见面试题(进阶)

⼆叉树常见⾯试题(进阶)⼀、常见题型1. 求两个节点的最近公共祖先;2. 求⼆叉树中最远的两个节点的距离;3. 由前序遍历和中序遍历重建⼆叉树(如:前序序列:1 2 3 4 5 6 - 中序序列:3 2 4 1 6 5);4. 判断⼀棵树是否是完全⼆叉树;5. 将⼆叉搜索树转换成⼀个排序的双向链表。

要求不能创建任何新的结点,只能调整树中结点指针的指向;6.求⼆叉树的宽度;7. 判断⼀棵⼆叉树是否是平衡⼆叉树;8.判断⼀颗⼆叉树是否是另⼀颗树的⼦树。

⼆、解题思路分析1.两个节点的最近公共祖先求两个节点的最近公共祖先可分为三种情况,分别为:(1)求搜索⼆叉树的最近公共祖先。

根据搜索⼆叉树的性质,左⼦树的所有节点⽐根节点⼩,右⼦树的所有节点⽐跟节点⼤。

如果两个节点都⽐根节点⼩,则递归左⼦树;如果两个节点都⽐跟节点⼤,则递归右⼦树;否则,两个节点⼀个在左⼦树,⼀个在右⼦树,则当前节点就是最近公共祖先节点。

1 Node* GetAncestor(Node* root, Node* x1, Node* x2)//1.该⼆叉树为搜索⼆叉树2 {3 assert(x1 && x2);4if (x1->_data <= root->_data && x2->_data <= root->_data)5 {6return GetAncestor(root->_left, x1, x2);//两个节都⼩于根节点,最近公共祖先在左⼦树中7 }8else if (x1->_data > root->_data && x2->_data > root->_data)9 {10return GetAncestor(root->_right, x1, x2);//两个节都⼤于根节点,最近公共祖先在左⼦树中11 }12else13return root; //⼀个在左⼦树,⼀个在右⼦树,找到公共祖先1415 }(2)三叉链,带⽗节点时求最近公共祖先,⼆叉树节点有指向⽗节点的指针。

一、二叉搜索树(BSTree)的概念

一、二叉搜索树(BSTree)的概念

⼀、⼆叉搜索树(BSTree)的概念参考⽹址:⼆叉搜索树⼜被称为⼆叉排序树,那么它本⾝也是⼀棵⼆叉树,那么满⾜以下性质的⼆叉树就是⼆叉搜索树:1、若左⼦树不为空,则左⼦树上左右节点的值都⼩于根节点的值2、若它的右⼦树不为空,则它的右⼦树上所有的节点的值都⼤于根节点的值3、它的左右⼦树也要分别是⼆叉搜索树===================================================================⼆、⼆叉搜索树的插⼊1、搜索插⼊之前我们先来说说它的搜索,像上图这样的⼀棵⼆叉搜索树,我们要查找某⼀个元素是很简单的。

因为它的节点分布是有规律的,所以查找⼀棵元素只需要如下的步骤就可以了:2、插⼊由于⼆叉搜索树的特殊性质确定了⼆叉搜索树中每个元素只可能出现⼀次,所以在插⼊的过程中如果发现这个元素已经存在于⼆叉搜索树中,就不进⾏插⼊。

否则就查找合适的位置进⾏插⼊。

第⼀种情况:_root为空直接插⼊,return true;第⼆种情况:要插⼊的元素已经存在如上⾯所说,如果在⼆叉搜索树中已经存在该元素,则不再进⾏插⼊,直接return false;第三种情况:能够找到合适位置===================================================================三、⼆叉搜索树的删除对于⼆叉搜索树的删除操作,主要是要理解其中的⼏种情况,写起来还是⽐较简单的。

当然⼀开始还是需要判断要删除的节点是否存在于我们的树中,如果要删除的元素都不在树中,就直接返回false;否则,再分为以下四种情况来进⾏分析:》要删除的节点⽆左右孩⼦》要删除的节点只有左孩⼦》要删除的节点只有右孩⼦》要删除的节点有左、右孩⼦删除⽅法解释:对于第⼀种情况,我们完全可以把它归为第⼆或者第三种情况,就不⽤再单独写⼀部分代码进⾏处理;》如果要删除的节点只有左孩⼦,那么就让该节点的⽗亲结点指向该节点的左孩⼦,然后删除该节点,返回true;》如果要删除的节点只有右孩⼦,那么就让该节点的⽗亲结点指向该节点的右孩⼦,然后删除该节点,返回true;对于上⾯这两种情况我们还应该在之前进⾏⼀个判断,就是判断这个节点是否是根节点,如果是根节点的话,就直接让根节点指向这个节点的左孩⼦或右孩⼦,然后删除这个节点。

阿里巴巴客服面试题及答案

阿里巴巴客服面试题及答案

阿里巴巴客服面试题及答案面试要通过层层考验,刷题肯定是必不可少的。

这一次面试题,不仅是知识的收获,还将间接地与技术大牛们做了直观的沟通,了解他们的出题思路与考察要点,并加以消化吸收。

这对自己技术能力本身就是一种极大的提升。

走上编程之路,不断丰富自己方能与世接轨,努力做最优秀的自己。

面试题001:如何实现一个高效的单向链表逆序输出?参考答案下面是其中一种写法,也可以有不同的写法,比如递归等。

面试题002:已知sqrt (2)约等于1.414,要求不用数学库,求sqrt (2)精确到小数点后10位。

考察点1.基础算法的灵活应用能力(二分法学过数据结构的同学都知道,但不一定往这个方向考虑;如果学过数值计算的同学,应该还要能想到牛顿迭代法并解释清楚)。

2.退出条件设计。

参考答案1. 已知sqrt(2)约等于1.414,那么就可以在(1.4, 1.5)区间做二分查找,如:a.high=>1.5b.low=>1.4c.mid => (high+low)/2=1.45d. 1.45*1.45>2 ? high=>1.45 : low => 1.45e.循环到c2. 退出条件前后两次的差值的绝对值<=0.0000000001, 则可退出。

代码示例:面试题003:给定一个二叉搜索树(BST),找到树中第K小的节点。

考察点1. 基础数据结构的理解和编码能力2. 递归使用示例如下图,输入K=3,输出节点值3说明:保证输入的K满足1<=K<=(节点数目)参考答案树相关的题目,第一眼就想到递归求解,左右子树分别遍历。

联想到二叉搜索树的性质,root大于左子树,小于右子树,如果左子树的节点数目等于K-1,那么root就是结果,否则如果左子树节点数目小于K-1,那么结果必然在右子树,否则就在左子树。

因此在搜索的时候同时返回节点数目,跟K做对比,就能得出结果了。

复杂度分析:时间复杂度: O(N),节点最多遍历一遍空间复杂度:O(1),(如果算上递归深度可以当做O(logN))面试题004:LRU缓存机制。

第八章-二叉搜索树

第八章-二叉搜索树
规则:若树中已有相同值的结点,则不进行插入操作。
二叉排序树的建立过程就是结点插入的过程每次插入时必须从根结 点开始, 新插入点一定是叶子结点。
root
36
25
43
48
12
27
38 45
2021/4/9
3
二叉树的应用——建立二叉排序树算法
插入26
root 25
k p
36 43
48
12
27
38 45
2021/4/9
16
二叉排序树结点的删除算法要点
不论是那一种情况,算法总是先形成以q 为根的二叉排序子树,然后根据f 与p的
关系,决定q是f的什么孩子
2021/4/9
17
删除二叉排序树中的指定结点算法
tpoiner locate (bitreptr root, elemtp x) { f=0; p=root;
while (p && p->data!=x ) if (p->data>x) { f=p; p=p->lc;} else {f=p; p=p->rc;}
• (1)试按表中元素的次序建立一棵二叉排序树,画出此二 叉排序树,并求在等概率情况下查找成功的平均查找长 度。
• (2)对上面的二叉排序树进行中序遍历,获得一有序表, 求在等概率情况下对此有序表进行二分查找时查找成功 的平均查找长度。
• 此题中的关键字是字符串,比较关键字需按英文字母在 ASCII码表中的编码大小进 行比较。以此原则建立的二 叉排序树如图所示。计算等概率情况下查找成功的平均 查找长度,将查找每个记录需要比较关键字的次数相加 除以记录个数即得,为(1+2+2+3+3+3+4+4+4+5+5+6)/12 =42/12。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

需要设计的主要函数: 读数据建搜索树T 判别一序列是否 与T构成一样的搜索树
如何建搜索树
Tree MakeTree( int N ) { Tree T; int i, V; scanf("%d", &V); T = NewNode(V); for (i=1; i<N; i++) { scanf("%d", &V); T = Insert(T, V); } return T; Tree Insert( Tree T, int V ) { if ( !T ) T = NewNode(V); else { if ( V>T->v ) T->Right = Insert( T->Right, V ); else T->Left = Insert( T->Left, V ); } return T; }
如何判别
int Judge( Tree T, int N ) { int i, V, flag = 0; /* flag: 0代表目前还一致,1代表已经不一致*/ scanf("%d", &V); if ( V!=T->v ) flag = 1; else T->flag = 1; for (i=1; i<N; i++) { scanf("%d", &V); if ( (!flag) && (!check(T, V)) ) flag = 1; } if (flag) return 0; else return 1; }
题意理解
### 输入样例: 42 3142 3412 3241 21 21 12 0 ### 输出样例: Yes No No 1 3 1 2 3 2 4 4
求解思路
两个序列是否对应相同搜索树的判别 1.分别建两棵搜索树的判别方法
根据两个序列分别建树,再判别树是否一样
2.不建树的判别方法
3124
{1 2} 3 {4}
void ResetT ( Tree T ) /* 清除T中各结点的flag标记 */ { if (T->Left) ResetT(T->Left); if (T->Right) ResetT(T->Right); T->flag = 0; } void FreeTree ( Tree T ) /* 释放T的空间 */ { if (T->Left) FreeTree(T->Left); if (T->Right) FreeTree(T->Right); free(T); }
}
Tree NewNode( int V ) { Tree T = (Tree)malloc(sizeof(struct TreeNode)); T->v = V; T->Left = T->Right = NULL; T->flag = 0; return T; }
如何判别
通过3 1 4 2构造的T
小白专场:
是否同一棵二叉搜索树
题意理解
给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,
一棵给定的二叉搜索树却可以由多种不同的插入序列得到。
例如,按照序列{2, 1, 3}和{2, 3, 1}插入初始为空的二叉搜索树, 都得到一样的结果。
问题:对于输入的各种插入序列,你需要判断它们是否能 生成一样的二叉搜索树。
搜索树表示
typedef struct TreeNode *Tree; struct TreeNode { int v; Tree Left, Right; int flag; };
程序框架搭建
int main() { 对每组数据 读入N和L 根据第一行序列建树T 依据树T分别判别后面的 L个序列是否能与T形成 同一搜索树并输出结果 return 0; } int main() { int N, L, i; Tree T; scanf("%d", &N); while (N) { scanf("%d", &L); T = MakeTree(N); for (i=0; i<L; i++) { if (Judge(T, N)) printf("Yes\n"); else printf("No\n"); ResetT(T); /*清除T中的标记flag*/ } FreeTree(T); scanf("%d", &N); } return 0; }
vs
3 4 1 2
{1 2} 3 {4}
3124
{1 2} 3 {4}Leabharlann vs3 2 4 1
{2 1} 3 {4}
求解思路
两个序列是否对应相同搜索树的判别 1.分别建两棵搜索树的判别方法
2.不建树的判别方法
3. 建一棵树,再判别其他序列是否与该树一致
求解思路
1. 搜索树表示
2. 建搜索树T
3. 判别一序列是否与搜索树T一致
3 1 2 4 1 2
3 2 4 1对应的树
3 4
如何判别序列3 2 4 1是否 与树T一致? 方法:在树T中按顺序搜索序列3 2 4 1中的每个数
如果每次搜索所经过的结点在前面均出现过,则一致
否则(某次搜索中遇到前面未出现的结点),则不一致
如何判别
int check ( Tree T, int V ) { if ( T->flag ) { if ( V<T->v ) return check(T->Left, V); else if ( V>T->v ) return check(T->Right, V); else return 0; } else { if ( V==T->v ) { T->flag = 1; return 1; } else return 0; } }
如何判别
int Judge( Tree T, int N ) { int i, V; /* 有bug版本 */ 3241 当发现序列中的某个数 与T不一致时,必须把 序列后面的数都读完!
scanf("%d", &V); if ( V!=T->v ) return 0; else T->flag = 1; for (i=1; i<N; i++) { scanf("%d", &V); if (!check(T, V) ) return 0; } return 1; }
相关文档
最新文档