文章目录
9.4小节——数据结构专题(2)->二叉查找树(BST)
9.4.1-二叉查找树的定义
二叉查找树是一种特殊的二叉树,又称为排序二叉树、二叉搜索树、二叉排序树等,其特点是其左子树结点数据域均小于或等于根结点的数据域,其右子树上所有结点的数据域均大于根结点的数据域,即二叉树中序遍历数据域递增有序。
9.4.2二叉查找树的基本操作
其基本操作有查找、插入、建树、删除。
#include<iostream>
#include<vector>
using namespace std;
#define ElemType int
struct node{
ElemType data;
struct node *lchild;
struct node *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);
}
}
//新建结点
node *newNode(int v){
node *Node = new node;//申请一个node型变量的地址空间
Node->data = v;//结点权值为v
Node->lchild = Node->rchild = NULL;//初始状态下没有左右孩子
return Node;//返回新建结点的地址
}
//插入操作
void insert(node *&root,int x){
if(root == NULL){
root = newNode(x);//新建结点,权值为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;//新建根结点root
for(int i = 0;i < n;i++){
insert(root,data[i]);
}
return 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;
}
删除以root为根结点的树中权值为x的结点
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前驱
root->data = pre->data;//用前驱覆盖root
deleteNode(root->lchild,pre->data);//在左子树中删除结点pre
}
else{//右子树不为空时
node *next = findMin(root->rchild);//找root后继
root->data = next->data;//用后继覆盖root
deleteNode(root->rchild,next->data);//在右子树中删除结点next
}
}
else if(root->data > x){
deleteNode(root->lchild,x);//在左子树中删除x
}
else{
deleteNode(root->rchild,x);//在右子树中删除x
}
}
9.4.3二叉查找树的性质
对二叉查找树进行中序遍历,遍历结果有序
PAT例题:PATA1043-Is-It-a-Binary-Search-Tree(25分)
链接:
https://pintia.cn/problem-sets/994805342720868352/problems/994805440976633856
//PATA1043-Is-It-a-Binary-Search-Tree
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
struct node{
int data;
node *left,*right;
};
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){//先序遍历,结果存在vi
if(root == NULL) return;
vi.push_back(root->data);
preOrder(root->left,vi);
preOrder(root->right,vi);
}
//镜像树先序遍历,结果存放于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){//后序遍历,结果存放于vi中
if(root == NULL) return;
postOrder(root->left,vi);
postOrder(root->right,vi);
vi.push_back(root->data);
}
//镜像树后序遍历,结果存放于vi
void postOrderMirror(node *root,vector<int> &vi){
if(root == NULL) return;
postOrderMirror(root->right,vi);
postOrderMirror(root->left,vi);
vi.push_back(root->data);
}
//origin存放初始序列
//pre、post为先序和后序,preM、postM为镜像树先序、后序
vector<int> origin,pre,preM,post,postM;
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);//将数据加入origin
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;
}
Codeup习题
链接: http://codeup.cn/contest.php?cid=100000613
问题A:二叉排序树
链接: http://codeup.cn/problem.php?cid=100000613&pid=0
//问题A:二叉排序树
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
struct node{
int data;
struct node *lchild;
struct node *rchild;
};
node *newNode(int data){
node *Node = new node;
Node->data = data;
Node->lchild = NULL;
Node->rchild = NULL;
return Node;
}
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;
}
void PreOrder(node *root){
if(root == NULL) return;
printf("%d ",root->data);
PreOrder(root->lchild);
PreOrder(root->rchild);
}
void InOrder(node *root){
if(root == NULL) return;
InOrder(root->lchild);
printf("%d ",root->data);
InOrder(root->rchild);
}
void PostOrder(node *root){
if(root == NULL) return;
PostOrder(root->lchild);
PostOrder(root->rchild);
printf("%d ",root->data);
}
int main(){
int n;
while(cin>>n){
int *num = new int[n];
// int num[1010];
node *root = NULL;
int x;
/* 法一:Create,但是有问题,尚不清楚,留坑
//用数组创建排序树
int cnt;
for(cnt=0;cnt<n;cnt++){
cin>>num[cnt];
}
Create(num,n);
// */
//法二:用insert一个个插入
for(int i=0;i<n;i++){
scanf("%d",&x);
insert(root,x);
}
PreOrder(root);
printf("\n");
InOrder(root);
printf("\n");
PostOrder(root);
printf("\n");
}
return 0;
}
问题 B: 二叉搜索树
链接: http://codeup.cn/problem.php?cid=100000613&pid=1
//问题B二叉搜索树
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
struct node{
int data;
struct node *lchild;
struct node *rchild;
};
node *newNode(int data){
node *Node = new node;
Node->data = data;
Node->lchild = NULL;
Node->rchild = NULL;
return Node;
}
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);
}
void PreOrder(node *root,vector<int> &v){
if(root == NULL) return;
v.push_back(root->data);
PreOrder(root->lchild,v);
PreOrder(root->rchild,v);
}
void InOrder(node *root,vector<int> &v){
if(root == NULL) return;
InOrder(root->lchild,v);
v.push_back(root->data);
InOrder(root->rchild,v);
}
void PostOrder(node *root,vector<int> &v){
if(root == NULL) return;
PostOrder(root->lchild,v);
PostOrder(root->rchild,v);
v.push_back(root->data);
}
int main(){
int n;
string str;
while(cin>>n){
if(n == 0) break;
cin >> str;
node *root1 = NULL;
vector<int> originPre;
vector<int> originIn;
for(int i = 0;i < str.length();i++) insert(root1,str[i] - '0');
PreOrder(root1,originPre);
InOrder(root1,originIn);
while(n--){
node *root2 = NULL;
vector<int> testPre;
vector<int> testIn;
cin>>str;
for(int i=0;i<str.length();i++) insert(root2,str[i] - '0');
int flag = 1;
PreOrder(root2,testPre);//检查前序是否一致
if(originPre != testPre){
flag = 0;
}
InOrder(root2,testIn);//检查中序是否一致
if(originIn != testIn){
flag = 0;
}
if(flag)
{
cout<<"YES"<<endl;
}
else
cout<<"NO"<<endl;
}
}
return 0;
}
树的遍历小结
二叉查找树(BST)是中序遍历其对应数据域递增的特殊二叉树,其操作过程得确保操作过后仍满足中序遍历数据域递增。