二叉搜索树
typedef struct node{
int val;
node*lt;//left可能会重名
node*rt;
node*fq;//指向父亲的指针
}node;
typedef struct node* tree;
插入节点
//插入节点
node *Insert(node *root,int num){
if(root==NULL){
root=new node;
root->val=num;
root->fq=NULL;
root->lt=NULL;
root->rt=NULL;
return root;
}
else{
if(num<root->val){
root->lt=Insert(root->lt,num);
if(root->lt)root->lt->fq=root;
}
else{
root->rt=Insert(root->rt,num);
if(root->rt)root->rt->fq=root;
}
}
return root;
}
node* Insert1(node*root,int v){
node* treenode=(node*)malloc(sizeof(node));
treenode->val=v;
treenode->lt=NULL;
treenode->rt=NULL;
treenode->fq=NULL;
node*t=root;
if(!t){
root=treenode;
return root;
}
else{
node*temp=t;
while(t){
temp=t;//最后退出循环时,temp记录所插节点的父亲
if(v>t->val){
t=t->rt;
}
else t=t->lt;
}
treenode->fq=temp;
if(v>temp->val){
temp->rt=treenode;
}
else{
temp->lt=treenode;
}
return root;
}
}
搜索节点
//搜索节点
node*Find(node*root,int v){
node*t=root;
if(!t)return NULL;//不要忘了不要访问空结点的内容!
if(t&&t->val==v)return t;//注意要先判断不为NULL再访问
else if(v>t->val)return Find(t->rt,v);
else return Find(t->lt,v);
}
查找最小/大关键字
//查找最小关键字
node*findMin(node*root){//最左下角
node*t=root;
while(t->lt){
t=t->lt;
}
return t;
}
//查找最da关键字
node*findMax(node*root){//最右下角
node*t=root;
while(t->rt){
t=t->rt;
}
return t;
}
给定一个元素查找后继(寻找前驱节点与寻找后继对称
//给定一个元素查找后继(寻找前驱节点与寻找后继对称
node*findNext(node*x){
//最大元素x 没有后继y
//后继y要么在x右子树最左下角(如果有右子树的话),要么后继是x的祖先
//且x在y的左子树的分支末端
//于是从x出发向上找祖先
//一旦发现x在某个祖先的左分支里,即
//也就是找到x或x的某个祖先q是上一个祖先f的左孩子,f就是后继
if(x->rt){
// return findMin(x);
//通过调用findMin函数或找右子树的最左下角节点(左优先,不一定最下
node*t=x->rt;
while(t->lt){
t=t->lt;
}
return t;
}
else{
node*f=x->fq;
node*q=x;
while(f){//根节点父亲为空,就是它了
if(f->lt==q){
return f;
// break;
}
q=f;
f=f->fq;
}
return f;//没找到就返回NULL了
}
}
返回节点所在层数(根节点第0层
int height(node*p){//给定一个节点求高度
node*t=p;
int cnt=0;
if(t==NULL)return 0;
while(t->fq){
t=t->fq;
cnt++;
}
return cnt;
}
判断二叉树是否平衡
int getHeight(TreeNode*root){
if(root==NULL)return 0;
return max(getHeight(root->left),getHeight(root->right))+1;
}
bool IsBalanced_Solution(TreeNode* pRoot) {
if(pRoot==NULL)return true;
if(abs(getHeight(pRoot->left)-getHeight(pRoot->right))>1)return false;
return IsBalanced_Solution(pRoot->left)&&IsBalanced_Solution(pRoot->right);
}
y节点取代x节点的位置,使y成为x父节点的孩子,便于删除操作
node* transfer(node*root,node*x,node*y){
//让y取代x的位置,使y成为x父节点的孩子,要返回新的树
if(x->fq==NULL){//x是根节点
root=y;
return root;
}
else{
node*f=x->fq;
if(x==f->lt){
f->lt=y;
}
else f->rt=y;
if(y)y->fq=x->fq;
return root;
}
}
删除节点
删除的节点既有左儿子又有右儿子——> 找后继节点
1、如果后继节点是删除节点的右儿子,好说,用有儿子换他,
2、否则 后继节点的右子树提上后继节点位置,后继节点提上删除节点位置
相当于自后继y以后整体大动向左边挪一位,而后继y身为x右子树中
最坐下节点,直接向左上飞若干步,y的右子树向上一步
node* Delete(node*root,node*d){
if(!d)return root;
// 删除的节点既有左儿子又有右儿子——>
//如果后继节点是删除节点的右儿子,好说,用有儿子换他,否则
// 相当于自后继y以后整体大动向左边挪一位,而后继y身为x右子树中
// 最坐下节点,直接向左上飞若干步,y的右子树向上一步
if(d->lt==NULL)root=transfer(root,d,d->rt);
else if(d->rt==NULL)root=transfer(root,d,d->lt);
else{
node*y=findNext(d);//找到d的后继节点y(有rt肯定能找到
//或者是findMin(root->rt,d),有右子树后继就是右子树中的最小节点
//但是可能后继节点就是删除节点的右孩子,没有分左支了
if(y!=d->rt){
root=transfer(root,y,y->rt);//y没有左孩子,否则左孩子才是后继
y->rt=d->rt;//这两句把后继节点y搞到d的位置
d->rt->fq=y; //把d的儿子、父亲都给y
}
root=transfer(root,d,y);
y->lt=d->lt;
d->lt->fq=y;
// y->fq=d->fq;
}
return root;
}
二叉搜索树 中序遍历 顺序输出数据
void inorder(node*root){
if(root){
inorder(root->lt);
cout<<root->val<<" ";
inorder(root->rt);
}
}
int num=0;
int res;
void inorder(node*root,int k){//寻找第k小的节点
if(root||k>=1){
inorder(root->lt,k);
// cout<<root->val<<" ";
if(++num==k)res=root->val;
inorder(root->rt,k);
}
}
void inorder(node* root){
if(root==NULL) return;
stack<node> s;
node* p=root;
while(!s.empty()||p!=NULL){
if(p){//循环将root及root左子树的所有结点的左孩子入栈
cout<<p->val<<endl;//中左右
s.push(p);
p=p->lt;
}
else{
p=s.top();
s.pop();
cout<<p->val<<endl;//左中右
p=p->right;
}
}
}
整体测试
#include<iostream>
#include <stdlib.h>
using namespace std;
typedef struct node{
int val;
node*lt;//left可能会重名
node*rt;
node*fq;//指向父亲的指针
}node;
typedef struct node* tree;
//插入节点
node *Insert(node *root,int num){
if(root==NULL){
root=new node;
root->val=num;
root->fq=NULL;
root->lt=NULL;
root->rt=NULL;
return root;
}
else{
if(num<root->val){
root->lt=Insert(root->lt,num);
if(root->lt)root->lt->fq=root;
}
else{
root->rt=Insert(root->rt,num);
if(root->rt)root->rt->fq=root;
}
}
return root;
}
node* Insert1(node*root,int v){
node* treenode=(node*)malloc(sizeof(node));
treenode->val=v;
treenode->lt=NULL;
treenode->rt=NULL;
treenode->fq=NULL;
node*t=root;
if(!t){
root=treenode;
return root;
}
else{
node*temp=t;
while(t){
temp=t;//最后退出循环时,temp记录所插节点的父亲
if(v>t->val){
t=t->rt;
}
else t=t->lt;
}
treenode->fq=temp;
if(v>temp->val){
temp->rt=treenode;
}
else{
temp->lt=treenode;
}
return root;
}
}
//搜索节点
node*Find(node*root,int v){
node*t=root;
if(!t)return NULL;//不要忘了不要访问空结点的内容!
if(t&&t->val==v)return t;//注意要先判断不为NULL再访问
else if(v>t->val)return Find(t->rt,v);
else return Find(t->lt,v);
}
//查找最小关键字
node*findMin(node*root){//最左下角
node*t=root;
while(t->lt){
t=t->lt;
}
return t;
}
//查找最da关键字
node*findMax(node*root){//最右下角
node*t=root;
while(t->rt){
t=t->rt;
}
return t;
}
//给定一个元素查找后继(寻找前驱节点与寻找后继对称
node*findNext(node*x){
//最大元素x 没有后继y
//后继y要么在x右子树最左下角(如果有右子树的话),要么后继是x的祖先
//且x在y的左子树的分支末端
//于是从x出发向上找祖先
//一旦发现x在某个祖先的左分支里,即
//也就是找到x或x的某个祖先q是上一个祖先f的左孩子,f就是后继
if(x->rt){
// return findMin(x);
//通过调用findMin函数或找右子树的最左下角节点(左优先,不一定最下
node*t=x->rt;
while(t->lt){
t=t->lt;
}
return t;
}
else{
node*f=x->fq;
node*q=x;
while(f){//根节点父亲为空,就是它了
if(f->lt==q){
return f;
// break;
}
q=f;
f=f->fq;
}
return f;//没找到就返回NULL了
}
}
int height(node*p){//给定一个节点求高度
node*t=p;
int cnt=0;
if(t==NULL)return 0;
while(t->fq){
t=t->fq;
cnt++;
}
return cnt;
}
node* transfer(node*root,node*x,node*y){
//让y取代x的位置,使y成为x父节点的孩子,要返回新的树
if(x->fq==NULL){//x是根节点
root=y;
return root;
}
else{
node*f=x->fq;
if(x==f->lt){
f->lt=y;
}
else f->rt=y;
if(y)y->fq=x->fq;
return root;
}
}
node* Delete(node*root,node*d){
if(!d)return root;
// 删除的节点既有左儿子又有右儿子——>
//如果后继节点是删除节点的右儿子,好说,用有儿子换他,否则
// 相当于自后继y以后整体大动向左边挪一位,而后继y身为x右子树中
// 最坐下节点,直接向左上飞若干步,y的右子树向上一步
if(d->lt==NULL)root=transfer(root,d,d->rt);
else if(d->rt==NULL)root=transfer(root,d,d->lt);
else{
node*y=findNext(d);//找到d的后继节点y(有rt肯定能找到
//或者是findMin(root->rt,d),有右子树后继就是右子树中的最小节点
//但是可能后继节点就是删除节点的右孩子,没有分左支了
if(y!=d->rt){
root=transfer(root,y,y->rt);//y没有左孩子,否则左孩子才是后继
y->rt=d->rt;//这两句把后继节点y搞到d的位置
d->rt->fq=y; //把d的儿子、父亲都给y
}
root=transfer(root,d,y);
y->lt=d->lt;
d->lt->fq=y;
// y->fq=d->fq;
}
return root;
}
void inorder(node*root){
if(root){
inorder(root->lt);
cout<<root->val<<" ";
inorder(root->rt);
}
}
int main()
{
node *root=NULL;
int n,m;
cin>>n;
int value;
for(int i=0; i<n; i++){
cin>>value;
root=Insert1(root,value);
}
inorder(root);//6 1 3 5 2 4 6
cout<<endl;
root=Insert1(root,666);
inorder(root);
cout<<endl;
node*p=Find(root,3);
cout<<p->val<<endl;
root=Delete(root,p);//删除4
inorder(root);
cout<<endl;
p=findMin(root);
cout<<p->val<<endl;
p=findNext(root->rt);//p的后继节点
cout<<p->val<<endl;
return 0;
}