二叉搜索树 基本操作

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉排序树也称为二叉搜索树,它是一种特殊的二叉树,满足以下性质: 1. 左子树中的所有节点的值均小于根节点的值; 2. 右子树中的所有节点的值均大于根节点的值; 3. 左子树和右子树也都是二叉排序树。 基本操作包括插入节点、删除节点和查找节点。下面是它们的实现: 1. 插入节点: 插入节点操作用于向二叉排序树中插入一个新节点。从根节点开始,比较插入节点的值与当前节点的值,如果小于当前节点的值,则进入左子树,否则进入右子树。直到找到一个空位置,将新节点插入到该位置。 示例代码如下: ```python class TreeNode: def __init__(self, val): self.val = val self.left = None self.right = None def insert_node(root, val): if root is None: return TreeNode(val) if val < root.val: root.left = insert_node(root.left, val) else: root.right = insert_node(root.right, val) return root ``` 2. 删除节点: 删除节点操作用于从二叉排序树中删除指定节点。分为三种情况: - 被删除节点没有子节点:直接删除即可; - 被删除节点只有一个子节点:将子节点替代被删除节点的位置; - 被删除节点有两个子节点:找到被删除节点的后继节点(右子树中最小的节点),将后继节点的值复制到被删除节点,然后删除后继节点。 示例代码如下: ```python def find_min(node): while node.left is not None: node = node.left return node def delete_node(root, val): if root is None: return root if val < root.val: root.left = delete_node(root.left, val) elif val > root.val: root.right = delete_node(root.right, val) else: if root.left is None: return root.right elif root.right is None: return root.left else: successor = find_min(root.right) root.val = successor.val root.right = delete_node(root.right, successor.val) return root ``` 3. 查找节点: 查找节点操作用于在二叉排序树中查找指定值的节点。从根节点开始,比较目标值与当前节点的值,如果小于当前节点的值,则进入左子树,否则进入右子树。如果找到匹配的节点,则返回该节点;如果遍历完整个树仍未找到匹配的节点,则返回空。 示例代码如下: ```python def search_node(root, val): if root is None or root.val == val: return root if val < root.val: return search_node(root.left, val) else: return search_node(root.right, val) ``` 以上是二叉排序树基本操作的实现。你可以根据需要调用这些函数来操作二叉排序树。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值