当前位置:首页 » 操作系统 » 二叉查找树查找算法

二叉查找树查找算法

发布时间: 2022-11-17 03:08:16

Ⅰ 二叉树查找树算法实现

#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -1
#define EQ(a,b) ((a)==(b))
#define LT(a,b) ((a)<(b))
typedef int ElemType;
typedef int Status;
typedef struct TElemType{
int key;
int num;
}TElemType;
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;

Status SearchBST(BiTree T,int key,BiTree f,BiTree &p){
if(!T) { p=f; return ERROR;}
else if(EQ(T->data.key,key)) { p=T; return OK; }
else if(LT(key,T->data.key))
return SearchBST(T->lchild,key,T,p);
else return SearchBST(T->rchild,key,T,p);
}
Status SearchBST1(BiTree T,int key,BiTree f,BiTree &p){
if(!T) { p=f; return ERROR;}
else if(EQ(T->data.key,key)) {
printf("%d %d",p->data.key,p->data.num);
p=T; return OK; }
else if(LT(key,T->data.key))
return SearchBST(T->lchild,key,T,p);
else return SearchBST(T->rchild,key,T,p);
}
Status InsertBST(BiTree &T,TElemType e){
BiTree s,p;
if(!SearchBST(T,e.key,NULL,p)){
s=(BiTree)malloc(sizeof(BiTNode));
s->data=e;
s->lchild=s->rchild=NULL;
if(!p) T=s;
else if(LT(e.key,p->data.key)) p->lchild=s;
else p->rchild=s;
return OK;
}
}
Status Output(TElemType e){
printf("%d ",e.key);
printf("%d\n",e.num);
}
Status PreOrderTraver( BiTree T){//二叉树先序遍历
if(T==NULL) return ERROR;
else{
Output(T->data);
PreOrderTraver(T->lchild);
PreOrderTraver(T->rchild);}
return OK;
}
int main()
{
BiTree T,f=NULL,q;
TElemType a;
int i,n,b;
printf("请输入你要创建的二叉排序树的结点个数:\n");
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",a.key);
scanf("%d",a.num);
InsertBST(T,a);
}
printf("请输入你要查找的关键字: ");{
scanf("%d",b);
if(SearchBST1(T,b,f,q)) printf("查找成功!\n");
else printf("查找失败!\n");}
printf("二叉树的先序遍历:\n");
PreOrderTraver(T);
system("pause");
return 0;
}
这个就是!希望可以帮助你!

Ⅱ 二叉排序树的构造和查找方法是什么

二叉排序树的构造过程:按照给定序列,以此将结点插入二叉排序树中,在二叉排序树中插入新结点,要保证插入后的二叉树仍符合二叉排序树的定义。

插入过程:若二叉排序树为空,则待插入结点*S作为根结点插入到空树中;

当非空时,将待插结点关键字S->key和树根关键字t->key进行比较,

若s->key = t->key,则无须插入,若s->key< t->key,则插入到根的左子树中,

若s->key> t->key,则插入到根的右子树中。而子树中的插入过程和在树中的插入过程相同,

如此进行下去,直到把结点*s作为一个新的树叶插入到二叉排序树中,或者直到发现树已有相同关键字的结点为止。
说明:

① 每次插入的新结点都是二叉排序树上新的叶子结点。

② 由不同顺序的关键字序列,会得到不同二叉排序树。

③ 对于一个任意的关键字序列构造一棵二叉排序树,其实质上对关键字进行排序。
查找的过程类似,从根结点开始进行比较,小于根结点的在左子树上,大于根结点的在右子树上,以此查找下去,直到查找成功或不成功(比较到叶子结点)。

Ⅲ 数据结构与算法-二叉树(Binary Tree)

    名词解释

        节点: 每个元素

        父子关系: 用来连线相邻节点之间的关系

        父节点: A节点就是B节点的父节点

        子节点:  B节点就是A节点的子节点

        兄弟节点: B、C、D这三个节点的父节点是同一个节点

        根结点: 没有父节点的节点

        叶子结点: 没有子节点的节点

        节点的高度: 节点到叶子结点到最长路径(边数)  (计数起点为0, 从下往上)

        节点的深度: 根节点到这个节点经历过的边个数  (计数起点为0, 从上往下)

        节点的层数:     节点到深度 + 1  (计数起点为1)

        树的高度: 根节点的高度

    特点

        最常用的树数据结构

        每个节点最多有两个子节点(左子节点、右子节点)

         满二叉树: 叶子节点全都在最底层,除了叶子节点之外,每个节点都有左右两个子节点

         完全二叉树:  叶子节点都在最底下两层,最后一层的叶子节点都 靠左排列 ,并且除了最后一层,其他层的节点个数都要达到最大

        二叉树存储方式

            数组顺序存储法

                通过数组下标来顺序存储数据 (i表示当前节点深度,从0开始)

                根节点: i = 1,左节点:2 * i,右节点: 2 * i + 1,父节点: i / 2

                完全二叉树采用此方式节省内存空间

            链式存储法

                每个节点需要存储三分数据:当前节点数据、左节点指针、右节点指针,比较占用空间                

            遍历

                常用方式

                前序遍历: 树任意节点,先打印当前节点,再打印它的左子树,最后打印它的右子树

                中序遍历: 树任意节点,先打印它的左子树,再打印当前节点,最后打印它的右子树

                后序遍历: 树任意节点,先打印它的左子树,再打印它的右子树,最后打印当前节点

                二叉树的前、中、后序遍历就是一个递归的过程

                时间复杂度是O(n)

                    每个节点最多被访问两次,遍历操作的时间复杂度跟节点的个数n成正比

特点

    二叉查找树为实现快速查找而生,支持快速查找一个数据、快速插入、快速删除一个数据

    特殊结构: 其左子树每个节点的值 < 树的任意一个节点的值 < 其右子树每个节点的值

            先取根节点,如果它等于要查找的数据,那就返回。

            如果要查找的数据比根节点的值小,那就在左子树中递归查找;

            如果要查找的数据比根节点的值大,那就在右子树中递归查找

            一般插入的数据在叶子节点上,从根节点开始依次比较要插入的数据和节点的大小关系

            如果插入数据比节点的数值大,并且节点的右子树为空,将新数据插到右子节点位置;

            如果不为空,就再递归遍历右子树,查找插入位置。

            如果插入数据比节点的数值小,并且节点的左子树为空,将新数据插到左子节点位置;

            如果不为空,就再递归遍历左子树,查找插入位置。

        针对要删除节点的子节点个数的不同,需分三种情况来处理

        1.如果要删除的节点没有子节点,步骤如下: (如图中的删除节点55)

            只需将父节点中指向要删除节点的指针置为null

        2.如果要删除的节点只有一个子节点,步骤如下: (如图中删除节点13)

            只需将父节点中指向要删除节点的指针,让它指向要删除节点的子节点即可

        3.如果要删除的节点有两个子节点,步骤如下: (如图中的删除节点18)

            首先,需要找到这个节点的右子树中的最小节点,把它替换到要删除的节点上;

            然后,再删除掉这个最小节点,因为最小节点肯定没有左子节点        

            删除操作,有个优化方案: 就是单纯将要删除的节点标记为“已删除”,

            这种方案删除操作就变简单很多,但是比较浪费内存空间

        支持快速地查找最大节点和最小节点、前驱节点和后继节点

        另外一种重要特性: 

            中序遍历二叉查找树,可以输出有序的数据序列,时间复杂度为O(n)

            因此,二叉查找树也叫作二叉排序树

        以上几种操作都默认树中节点存储的都是数字,而且都是不存在键值相同的情况

        实际应用场景中采用对象的某个字段作为键值来构建二叉查找树,其他字段称为卫星数据

        如果存储的两个对象键值相同,两种解决方案

        1.把值相同的数据都存储在同一个节点(采用链表或支持动态扩容的数组等数据结构)   

        2.每个节点只存储一个数据,把这个新插入的数据当作大于这个节点的值来处理,如下图:

        查找操作

            当查找数据时遇到值相同的节点,继续在右子树中查找,直到遇到叶子节点才停止。

            这样就把键值等于要查找值的所有节点都查找出来        

            删除操作

                先查找到每个要删除的节点,然后再按前面讲的删除操作的方法,依次删除

        对于同一组数据可构造不同二叉查找树。查找、插入、删除操作的执行效率都不一样

        图最左边树,根节点的左右子树极度不平衡,退化成链表,查找时间复杂度为O(n)

        最理想的情况,二叉查找树是一棵完全二叉树(或满二叉树)

        时间复杂度都跟树的高度成正比,也就是O(height)

        树的高度就等于最大层数减一,为了方便计算,我们转换成层来表示

        满二叉树: 下一层节点个数是上一层的2倍,第K层包含节点个数就是2^(K-1)

        完全二叉树: 假设最大层数是L,总的节点个数n,它包含的节点个数在1个到2^(L-1)个之间

            L的范围是[ , +1],完全二叉树的高度小于等于

            极度不平衡的二叉查找树,它的查找性能肯定不能满足我们的需求

        平衡二叉查找树: 树的高度接近logn,时间复杂度较稳定为O(logn)

    1.排序对比

        散列表中的数据是无序存储的,如果要输出有序的数据,需要先进行排序

        二叉查找树只需要中序遍历,就可以在O(n)的时间复杂度内,输出有序的数据序列

    2.性能稳定性对比

        散列表扩容耗时很多,而且当遇到散列冲突时,性能不稳定

        最常用的平衡二叉查找树的性能非常稳定,时间复杂度稳定在O(logn)

    3.时间复杂度对比

        散列表查找等操作时间复杂度是常量级,因存在哈希冲突,这个常量不一定比logn小

        另外加上哈希函数的耗时,也不一定就比平衡二叉查找树的效率高

    4.结构设计对比

        散列表构造比较复杂,需要考虑:散列函数设计、冲突解决办法、扩容、缩容等

        平衡二叉查找树只需要考虑平衡性,而且目前这个的解决方案较成熟、固定

    5.空间复杂度

        散列表: 避免过多散列冲突,装载因子不能太大,特别基于开放寻址法,否则浪费太多空间

            

        

Ⅳ 二叉排序树查找的二叉排序树查找的程序实现:

5. 二叉排序树的删除:
假设被删结点是*p,其双亲是*f,不失一般性,设*p是*f的左孩子,下面分三种情况讨论:
⑴ 若结点*p是叶子结点,则只需修改其双亲结点*f的指针即可。
⑵ 若结点*p只有左子树PL或者只有右子树PR,则只要使PL或PR 成为其双亲结点的左子树即可。
⑶ 若结点*p的左、右子树均非空,先找到*p的中序前趋结点*s(注意*s是*p的左子树中的最右下的结点,它的右链域为空),然后有两种做法:
① 令*p的左子树直接链到*p的双亲结点*f的左链上,而*p的右子树链到*p的中序前趋结点*s的右链上。
② 以*p的中序前趋结点*s代替*p(即把*s的数据复制到*p中),将*s的左子树链到*s的双亲结点*q的左(或右)链上。
6. 删除算法演示 :
7. 二叉排序树的查找:
在二叉排序树中进行查找的过程和二分查找类似,也是一个逐步缩小查找范围的过程。若查找成功,则是走了一条从根结点到待查结点的路径;若查找失败,则是走了一条根结点到某个叶子结点的路径。因此,查找过程中和关键字比较的次数不超过树的深度。
由于含有n个结点的二叉排序树不唯一,形态和深度可能不同。故含有n个结点的二叉排序树的平均查找长度和树的形态有关。
最好的情况是: 二叉排序树和二叉判定树形态相同。
最坏的情况是: 二叉排序树为单支树,这时的平均查找长度和顺序查找时相同。
最坏情况示例
就平均性能而言,二叉排序树上的查找和二分查找相差不大,并且二叉排序树上的插入和删除结点十分方便,无须大量移动结点。

Ⅳ 二叉树算法是什么

二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。

二叉树的第i层至多有2^(i 1)个结点;深度为k的二叉树至多有2^k 1个结点;对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点数为n2,则n0 = n2 + 1。二叉树算法常被用于实现二叉查找树和二叉堆。

二叉树是每个节点最多有两个子树的有序树。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。

(5)二叉查找树查找算法扩展阅读:

二叉树也是递归定义的,其结点有左右子树之分,逻辑上二叉树算法有五种基本形态:

1、空二叉树——(a)

2、只有一个根结点的二叉树——(b);

3、右子树为空的二叉树——(c);

4、左子树为空的二叉树——(d);

5、完全二叉树——(e)

注意:尽管二叉树与树有许多相似之处,但二叉树不是树的特殊情形。

Ⅵ C语言数据结构(二叉排序树的创建及查找算法)

int BSTInsert(BTNode *&T,int k)//修改此处,理由:引用型操作

Ⅶ 二叉树算法是什么

二叉树是每个节点最多有两个子树的有序树。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。



性质

1、在二叉树中,第i层的结点总数不超过2^(i-1)。

2、深度为h的二叉树最多有2^h-1个结点(h>=1),最少有h个结点。

3、对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1。


Ⅷ 二叉树查找法

是错误的

二叉树是一种很有用的非线性结构,具有以下两个特点:
①非空二叉树只有一个根结点;
②每一个结点最多有两棵子树,且分别称为该结点的左子树和右子树。
由以上特点可以看出,在二叉树中,每一个结点的度最大为2,即所有子树(左子树或右子树)也均为二叉树,而树结构中的每一个结点的度可以是任意的。另外,二叉树中的每个结点的子树被明显地分为左子树和右子树。在二叉树中,一个结点可以只有左子树而没有右子树,也可以只有右子树而没有左子树。当一个结点既没有左子树也没有右子树时,该结点即为叶子结点。
(2)二叉树的基本性质
二叉树具有以下几个性质:
性质1:在二叉树的第k层上,最多有2k-1(k≥1)个结点;
性质2:深度为m的二叉树最多有2m-1个结点;
性质3:在任意一棵二叉树中,度为0的结点(即叶子结点)总是比度为2的结点多一个。
性质4:具有n个结点的二叉树,其深度至少为〔log2n〕+1,其中〔log2n〕表示取log2n的整数部分。

Ⅸ 二叉查找树算法

#include <iostream>using namespace std;typedef struct _node{ int data; struct _node *pLeftPtr; struct _node *pRightPtr;}BTreeNode;class BinarySearchTree{public: BinarySearchTree(); ~BinarySearchTree(); bool Create(int* pIntArray,int arrLength); bool Insert(int data); // 查找节点,searchLength为搜索长度,返回值为true表示指定的数据存在,否则不存在 bool Find(int data, int* searchLength); // 中序输出二叉树 void MidOutput(); // 释放内存 void Destroy(); void Delete(int data);protected: bool Insert(BTreeNode* pRoot, int data); bool Find(BTreeNode* pRoot,int data, int *searchLength); void Delete(BTreeNode* &pRoot, int data); void MidOutput(BTreeNode* pRoot); void Destroy(BTreeNode* pRoot);private: BTreeNode* m_pRoot; //二叉搜索树根节点};BinarySearchTree::BinarySearchTree(){ m_pRoot = NULL;}BinarySearchTree::~BinarySearchTree(){ Destroy();}bool BinarySearchTree::Create(int* pIntArray,int arrLength){ for(int i=0; i<arrLength; i++) { if(!Insert(*(pIntArray+i))) return false; } return true;}bool BinarySearchTree::Insert(BTreeNode* pRoot, int data){ BTreeNode* pNewNode = new BTreeNode; if(pNewNode == NULL) return false; pNewNode->data = data; pNewNode->pLeftPtr = NULL; pNewNode->pRightPtr = NULL; BTreeNode* pCurrentNode = pRoot; BTreeNode* pParentNode = pCurrentNode;// 保存父节点的指针 int flag = 0;// 标记插入节点的位置 if(pCurrentNode == NULL) { m_pRoot = pNewNode; }else{ while(pCurrentNode) { if(data < pCurrentNode->data) { pParentNode = pCurrentNode; pCurrentNode = pCurrentNode->pLeftPtr; flag = 0; }else if(data > pCurrentNode->data){ pParentNode = pCurrentNode; pCurrentNode = pCurrentNode->pRightPtr; flag = 1; } } if(flag == 0) { pParentNode->pLeftPtr = pNewNode; }else{ pParentNode->pRightPtr = pNewNode; } } return true; }bool BinarySearchTree::Insert(int data){ return Insert(m_pRoot,data);}bool BinarySearchTree::Find(BTreeNode* pRoot,int data, int *searchLength){ if(pRoot == NULL) { *searchLength = 0; return false; } BTreeNode* pCurrentNode = pRoot; static int length = 0; while(pCurrentNode != NULL) { if(data == pCurrentNode->data) { *searchLength = length; cout<<"数字"<<data<<"存在二叉树中,查找长度为: "<<endl<<length<<endl; return true; }else if(data < pCurrentNode->data) { length ++; pCurrentNode = pCurrentNode->pLeftPtr; }else{ length ++; pCurrentNode = pCurrentNode->pRightPtr; } } *searchLength = length; cout<<"数字"<<data<<"不在二叉树中,查找长度为: "<<endl<<length<<endl; length = 0; // 每次查找结束,重新赋值为0 return false;}bool BinarySearchTree::Find(int data, int* searchLength){ return Find(m_pRoot,data,searchLength);}void BinarySearchTree::Destroy(BTreeNode* pRoot){ BTreeNode* pCurrentNode = pRoot; if(pCurrentNode == NULL) return; Destroy(pCurrentNode->pLeftPtr); Destroy(pCurrentNode->pRightPtr); delete pCurrentNode; m_pRoot = NULL;}void BinarySearchTree::Destroy(){ Destroy(m_pRoot);}void BinarySearchTree::MidOutput(BTreeNode* pRoot){ if(pRoot) { MidOutput(pRoot->pLeftPtr); cout<<pRoot->data <<" "; MidOutput(pRoot->pRightPtr); }}void BinarySearchTree::MidOutput(){ MidOutput(m_pRoot);}void BinarySearchTree::Delete(int data){ Delete(m_pRoot,data);}void BinarySearchTree::Delete(BTreeNode* &pRoot, int data){ if(!pRoot) return; else if(data == pRoot->data){ if(pRoot->pLeftPtr == NULL && pRoot->pRightPtr == NULL) // 叶子节点 { delete pRoot; pRoot = NULL; }else if(pRoot->pLeftPtr != NULL && pRoot->pRightPtr == NULL){ // 只有左子树 BTreeNode* pNode = pRoot->pLeftPtr; delete pRoot; pRoot = pNode; }else if(pRoot->pLeftPtr == NULL && pRoot->pRightPtr != NULL){ // 只有右子树 BTreeNode* pNode = pRoot->pRightPtr; delete pRoot; pRoot = pNode; }else{ // 有左右子树 // 找到左子树的最大节点 BTreeNode* pCurrentNode = pRoot->pLeftPtr; BTreeNode* pParentNode = NULL; while(pCurrentNode->pRightPtr != NULL) { pParentNode = pCurrentNode; pCurrentNode = pCurrentNode->pRightPtr; } pRoot->data = pCurrentNode->data; if(pParentNode) { pParentNode->pRightPtr = pCurrentNode->pLeftPtr; }else{ pRoot->pLeftPtr= pCurrentNode->pLeftPtr; } delete pCurrentNode; } }else if(data < pRoot->data) Delete(pRoot->pLeftPtr, data); else Delete(pRoot->pRightPtr, data);}void main(){ int data[8]; cout<<"请输入整形数据, 数据用空格隔开, 回车键结束输入"<<endl; for(int i=0; i<8; i++) cin>>data[i]; // int data[8] = {13,15,6,20,14,5,7,18}; BinarySearchTree tree; tree.Create(data,sizeof(data)/sizeof(data[0])); cout<<"插入数据后的二叉树为: "<<endl; tree.MidOutput(); cout<<endl; int len_1=0; int len_2=0; tree.Find(14,&len_1); tree.Find(21,&len_2); tree.Delete(20); cout<<"删除数字20后的二叉树结果: "<<endl; tree.MidOutput(); cout<<endl; tree.Delete(15); cout<<"删除数字15后的二叉树结果: "<<endl; tree.MidOutput(); cout<<endl;}

Ⅹ 二叉树查找和二分查找是同一算法吗

两者的算法思路其实很像:比中间的小就在剩下的左边,大就在剩下的右边找
但是:
二叉树查找一般习惯是在链式存储上进行,为一个树形结构
二分查找一定在顺序存储上进行

热点内容
内置存储卡可以拆吗 发布:2025-05-18 04:16:35 浏览:335
编译原理课时设置 发布:2025-05-18 04:13:28 浏览:378
linux中进入ip地址服务器 发布:2025-05-18 04:11:21 浏览:612
java用什么软件写 发布:2025-05-18 03:56:19 浏览:32
linux配置vim编译c 发布:2025-05-18 03:55:07 浏览:107
砸百鬼脚本 发布:2025-05-18 03:53:34 浏览:943
安卓手机如何拍视频和苹果一样 发布:2025-05-18 03:40:47 浏览:739
为什么安卓手机连不上苹果7热点 发布:2025-05-18 03:40:13 浏览:803
网卡访问 发布:2025-05-18 03:35:04 浏览:511
接收和发送服务器地址 发布:2025-05-18 03:33:48 浏览:371