100000613 - 《算法笔记》9.4小节——数据结构专题(2)->二叉查找树(BST)

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)是中序遍历其对应数据域递增的特殊二叉树,其操作过程得确保操作过后仍满足中序遍历数据域递增。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李霁明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值