当前位置: 首页 > news >正文

做网站与做软件中国招标采购网

做网站与做软件,中国招标采购网,渭南经开区,青岛海川建设集团网站目录 二叉查找树的定义 二叉查找树的基本操作 查找 插入 建立 删除 二叉树查找树的性质 二叉查找树的定义 二叉查找树是一种特殊的二叉树,又称为排序二叉树、二叉搜索树、二叉排序树。 二叉树的递归定义如下: (1)要么二…

目录

二叉查找树的定义

二叉查找树的基本操作

查找

插入

建立

删除

二叉树查找树的性质

二叉查找树的定义

二叉查找树是一种特殊的二叉树,又称为排序二叉树、二叉搜索树、二叉排序树。

二叉树的递归定义如下:

(1)要么二叉查找树是一棵空树。

(2)要么二叉查找树由根节点、左子树、右子树组成,其中左子树和右子树都是二叉查找树,且左子树上所以结点的数据域均小于或等于根节点的数据域,右子树上的所有结点的数据域均大于根节点的数据域。

二叉查找树的基本操作

查找

进行二叉树的查找操作时,由于无法确定二叉树的具体特性,因此只能对左右子树都进行递归遍历。但是二叉查找树的性质决定了可以只选择一棵子树进行遍历。因此查找将会是从根节点查找的一条路径,故最坏时间复杂度是O\left ( h \right ),其中h是二叉查找树的高度。于是就可以得到查找操作的基本思路:

(1)如果当前根节点root为空,说明查找失败,返回。

(2)如果需要查找的x等于当前根节点的数据域root->data,查找成功,访问。

(3)如果需要查找的x小于当前根节点的数据域root->data,说明应该往左子树查找,因此向root->lchild递归。

(4)如果需要查找的x大于当前结点的数据域root->data,则应该往右子树查找,因此向root->rchild递归。

void search(node* root,int x){if(root==NULL){printf("search failed\n");return;}if(x==root->data){printf("%d\n",root->data);}else if(x<root->data){search(root->lchild,x);}else{search(root->rchild,x);}
}

可以看到,和普通二叉树的查找函数不同,二叉查找树的查找在于对左右子树的选择递归。在普通二叉树中,无法确定需要查找的值x到底是在左子树还是右子树,但是在二叉查找树中就可以确定,因为二叉查找树中的数据域顺序总是左子树<根节点<右子树。

插入

对一棵二叉查找树来说,查找某个数据域的结点一定是沿着确定的路径进行的。因此,当对某个需要查找的值在二叉查找树中查找成功,说明结点已经存在。反之,如果这个需要查找的值在二叉查找树中查找失败,那么说明查找失败的地方一定是结点需要插入的地方。因此可以在上面查找操作的基础上,在root==NULL时新建需要插入的点。

void insert(node* &root,int x){if(root==NULL){root=newNode[x];return;}if(x==root->data){return;}else if(x<root->data){insert(root->lchild,x);}else{insert(root->rchild,x);}
}

建立

node* Create(int data[],int n){node* root=NULL;for(int i=0;i<n;i++){insert(root,data[i]);}return root;
}

需要注意的是,即使是一组相同的数字,如果插入它们的顺序不同,最后生成的二叉查找树也可能不同。

删除

把二叉查找树中比结点权值小的最大结点称为该结点的前驱,而把比结点权值大的最小结点称为该结点的后继。显然,结点的前驱是该结点左子树的最右结点(也就是从左子树根节点开始不断沿着rchild往下直到rchild为NULL时的结点),而结点的后继则是该结点右子树的最左节点(也就是从右子树根节点开始不断沿着lchild往下直到lchild为NULL时的结点)。下面两个函数用来寻找以root为根的树中最大或最小权值的结点,用以辅助寻找结点的前驱和后继:

//寻找以root为根结点的树中的最大权值结点 
node* findMax(node* root){while(root->rchild!=NULL){root=root->rchild;}return root;
}
//寻找以root为根结点的树中的最小权值结点
node* findMin(node* root){while(root->lchild!=NULL){root=root->lchild;}return root;
} 

删除操作的基本思路如下:

(1)如果当前结点root为空,说明不存在权值为给定权值x的结点,直接返回。

(2)如果当前结点root的权值恰为给定的权值x,说明找到了想要删除的结点,此时进入删除处理。如果当前结点root不存在左右孩子,说明是叶子节点,直接删除。如果当前结点root存在左孩子,那么在左子树中寻找结点前驱pre,然后让前驱的数据覆盖root,接着在左子树中删除结点pre。如果当前结点root存在右孩子,那么在右子树中寻找结点后继next,然后让next的数据覆盖root,接着在右子树中删除结点next。

(3)如果当前结点root的权值大于给定权值的x,则在左子树中递归删除权值为x的结点。

(4)如果当前结点root的权值小于给定权值的x,则在右子树中递归删除权值为x的结点。

//寻找以root为根结点的树中的最大权值结点 
node* findMax(node* root){while(root->rchild!=NULL){root=root->rchild;}return root;
}
//寻找以root为根结点的树中的最小权值结点
node* findMin(node* root){while(root->lchild!=NULL){root=root->lchild;}return root;
} 
void deleteNode(node* &root,int x){if(root==NULL){return;}if(root->data==x){if(root->lchild==NULL&&root->rchild==NULL){root==NULL;}else if(root->lchild!=NULL){node* pre=findMax(root->lchild);root->data=pre->data;deleteNode(root->lchild,pre->data);}else{node* next=findMin(root->rchild);root->data=next->data;deleteNode(root->rchild,next->data);}}else if(root->data>x){deleteNode(root->lchild,x);}else{deleteNode(root->rchild,x);}
}

但是也要注意,总是优先删除前驱或后继容易导致树的左右子树高度极度不平衡,使得二叉查找树退化成一条链。解决这一问题的办法有两种:一种是每次交替删除前驱或后继;另一种是记录子树高度,总是优先在高度较高的一棵子树里删除结点。

二叉树查找树的性质

二叉查找树一个实用的性质:对二叉查找树进行中序遍历,遍历的结果是有序的

另外,如果合理调整二叉查找树的形态,使得树上的每个结点都尽量有两个子节点,这样整个二叉查找树的高度就会很低,也即树的高度大概在logN的级别。

例题

给出N个正整数来作为一棵二叉排序树的结点插入顺序,问:这串序列是否是该二叉排序树的先序序列或是该二叉排序树的镜像树的先序序列。所谓镜像树是指交换二叉树的所有结点的左右子树而形成的树(也即左子树所有结点数据域大于或等于根节点,而根节点数据域小于右子树所有结点的数据域)。如果是,则输出YES,并输出对应的树的后序序列;否则,输出NO。

思路

通过给定的插入序列,构建出二叉排序树。对镜像树的先序遍历只需要在原树的先序遍历时交换左右子树的访问顺序即可。

//镜像树先序遍历,结果存放于vi
void preordermirror(node* root,vector<int>&vi){if(root==NULL){return;}vi.push_back(root->data);preordermirror(root->right,vi);preordermirror(root->left,vi);
} 

注意点

使用vector来存放初始序列、先序序列、镜像树先序序列,可以方便相互之间的比较。若使用数组,则比较操作需要使用循环才能实现。

#include<cstdio>
#include<vector>
using namespace std;
struct node{int data;node* left,*right;
}; 
vector<int> origin,pre,preM,post,postM;
void insert(node* &root,int data){if(root==NULL){root=new node;root->data=data;root->left=root->right=NULL;return;}if(data<root->data){insert(root->left,data);}else{insert(root->right,data);}
}
void preorder(node* root,vector<int> &vi){if(root==NULL){return;}vi.push_back(root->data);preorder(root->left,vi);preorder(root->right,vi);
}
void preordermirror(node* root,vector<int> &vi){if(root==NULL){return;}vi.push_back(root->data);preordermirror(root->right,vi);preordermirror(root->left,vi);
}
void postorder(node* root,vector<int> &vi){if(root==NULL){return;}postorder(root->left,vi);postorder(root->right,vi);vi.push_back(root->data);
}
void postordermirror(node* root,vector<int> &vi){if(root==NULL){return;}postordermirror(root->right,vi);postordermirror(root->left,vi);vi.push_back(root->data);
}
int main(){int n,data;node* root=NULL;scanf("%d",&n);for(int i=0;i<n;i++){scanf("%d",&data);origin.push_back(data);insert(root,data);}preorder(root,pre);preordermirror(root,preM);postorder(root,post);postordermirror(root,postM);if(origin==pre){printf("YES\n");for(int i=0;i<post.size();i++){printf("%d",post[i]);if(i<post.size()-1){printf(" ");}}}else if(origin==preM){printf("YES\n");for(int i=0;i<postM.size();i++){printf("%d",postM[i]);if(i<postM.size()-1){printf(" ");}}}else{printf("NO\n");return 0;}
}
http://www.yayakq.cn/news/846189/

相关文章:

  • 成都建设厅官方网站深圳全网推广怎么投放
  • 免费申请网站首选百度构建新发展格局
  • 做海报找素材的网站无上升级系统
  • 网站模板 静态模版微博wordpress
  • 网站建设方案文库张家港做网站费用
  • 网站cms系统排名站长网站的优势
  • 做网站好比做房子品牌建设典型案例材料
  • 做网站如何添加视频芜湖网站建设开发
  • 拥有自己的网站网络营销的支持条件是什么
  • 辽宁省住房和城乡建设厅网站打不开数据分析工具
  • 银行网站建设中国摄影官方网站
  • 嘉兴论坛网站建设php网站建设含义
  • 北京撒网站设计软件著作权申请
  • wordpress网站代码文件太多手机对比参数配置平台
  • 二手书的网站建设网站开发合同需要交印花税吗
  • 如何用手机做网站吗自己做的表白网站
  • 网站做专业团队wordpress 空白页面
  • 东营微信开发网站建设怎样防止别人利用自己的电脑做网站服务器
  • 品牌型网站制作价格飞猪关键词排名优化
  • 招标网站排名上传网站 php 服务器
  • 网站建设验收方案微信小商店和小程序商城的区别
  • 网站栏目相关内容在哪采集啊设计类网站策划书
  • 电子商务网站建设需求分析网页界面设计原则
  • 10元网站备案凡科做的网站百度不到
  • 优质做网站价格网站开发代淘宝店铺装修
  • 一了网站广州网站建设程序员培训
  • 做系统用哪个网站好腾讯云服务器学生机
  • php网站开发百度云wordpress的安装原理
  • 如何将网站排名做高2021年最新军事新闻
  • 翻译网站素材开网站空间流量怎么选择