zoukankan      html  css  js  c++  java
  • 基本数据结构 —— 二叉搜索树(C++实现)

    什么是二叉搜索树

    二叉搜索树(英语:Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树:

    • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
    • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
    • 它的左、右子树也分别为二叉搜索树。

    二叉搜索树如何储存数值

    如图所示:

    所有的节点,都满足左子树上的所有节点都比自己的小,而右子树上的所有节点都比自己大这个条件。

    二叉搜索树的操作

    因为二叉搜索树的性质,二叉搜索树能够高效地进行如下操作:

    • 插入一个数值;
    • 查询是否包含某个数值;
    • 删除某个数值

    如果共有n个元素,那么平均每次操作需要O(logn)的时间。
    接下来用C++来实现以上操作。首先定义节点结构体如下:

    node* insert(node* p,int x)
    {
    	if(!p)
    	{
    		auto q = new node(x);
    		return q;
    	}
    	else
    	{
    		if(x < p->val) p->lch = insert(p->lch,x);
    		else p->rch = insert(p->rch,x);
    		return p;
    	}
    }
    

    插入一个数值

    如图所示:

    node* insert(node* p,int x)
    {
    	if(!p) //空树
    	{
    		auto q = new node(x);
    		return q;
    	}
    	else
    	{
    		if(x < p->val) p->lch = insert(p->lch,x);
    		else p->rch = insert(p->rch,x);
    		return p;
    	}
    }
    

    查询是否包含某个数值

    如图所示:

    bool find(node* p,int x)
    {
    	if(!p) return false;
    	if(x == p->val) return true;
    	if(x < p->val) return find(p->lch,x);
    	else return find(p->rch,x);
    } 
    

    删除某个数值

    数值的删除比起之前提到的操作要稍微麻烦一些。例如,我们要删除数值15。如果删除了15所在的节点,那么它的两个儿子10和17就悬空了。于是,把11提到15所在的位置就可以解决问题。如图所示:

    一般来说,需要根据下面几种情况分别进行处理:

    • 需要删除的节点没有左儿子,那么就把右儿子提上去。
    • 需要删除的节点的左儿子没有右儿子,那么就把左儿子提上去。
    • 以上两种情况都不满足的话,就把左儿子的子孙中最大的节点提到需要删除的节点上。
    node* remove(node* p,int x)
    {
    	if(!p) return NULL;
    	if(x < p->val) p->lch = remove(p->lch,x);
    	else if(x > p->val) p->rch = remove(p->rch,x);
    	else
    	{
    		if(p->lch == NULL) //需要删除的节点没有左儿子 
    		{
    			auto q = p->rch;
    			delete p;
    			return q;
    		}
    		else if(p->lch->rch == NULL) //需要删除的节点的左儿子没有右儿子 
    		{
    			auto q = p->lch;
    			q->rch = p->rch;
    			delete p;
    			return q; 
    		}
    		else
    		{
    			auto q = p->lch;
    			while(q->rch->rch != NULL) q = q->rch;
    			auto r = q->rch;
    			q->rch = r->lch;
    			r->lch = p->lch;
    			r->rch = p->rch;
    			delete p;
    			return r;
    		}
    		return p;
    	}
    }
    

    测试代码

    #include<iostream>
    #include<algorithm>
    #include<queue>
    
    using namespace std;
    
    struct node{
    	int val;
    	node *lch,*rch;
    	node(int value): val(value),lch(NULL),rch(NULL){ }
    }; 
    node* insert(node* p,int x)
    {
    	if(!p)
    	{
    		auto q = new node(x);
    		return q;
    	}
    	else
    	{
    		if(x < p->val) p->lch = insert(p->lch,x);
    		else p->rch = insert(p->rch,x);
    		return p;
    	}
    }
    bool find(node* p,int x)
    {
    	if(!p) return false;
    	if(x == p->val) return true;
    	if(x < p->val) return find(p->lch,x);
    	else return find(p->rch,x);
    } 
    node* remove(node* p,int x)
    {
    	if(!p) return NULL;
    	if(x < p->val) p->lch = remove(p->lch,x);
    	else if(x > p->val) p->rch = remove(p->rch,x);
    	else
    	{
    		if(p->lch == NULL) //需要删除的节点没有左儿子 
    		{
    			auto q = p->rch;
    			delete p;
    			return q;
    		}
    		else if(p->lch->rch == NULL) //需要删除的节点的左儿子没有右儿子 
    		{
    			auto q = p->lch;
    			q->rch = p->rch;
    			delete p;
    			return q; 
    		}
    		else
    		{
    			auto q = p->lch;
    			while(q->rch->rch != NULL) q = q->rch;
    			auto r = q->rch;
    			q->rch = r->lch;
    			r->lch = p->lch;
    			r->rch = p->rch;
    			delete p;
    			return r;
    		}
    		return p;
    	}
    }
    void printTree(node* root)
    {
    	queue<node*> q;
    	q.push(root);
    	while(!q.empty())
    	{
    		auto p = q.front();q.pop();
    		if(p)
    		{
    			cout << p->val << " ";
    			q.push(p->lch);
    			q.push(p->rch);
    		} 
    	}
    	cout << endl;
    }
    int main() {
    	node* root = insert(NULL,7);
    	insert(root,2);
    	insert(root,15);
    	insert(root,1);
    	insert(root,5);
    	insert(root,10);
    	insert(root,17);
    	insert(root,4);
    	insert(root,6);
    	insert(root,8);
    	insert(root,11);
    	insert(root,16);
    	insert(root,19);
    	if(find(root,15)) cout << "find 15" << endl;
    	else cout << "can not find 15" << endl;
    	if(find(root,3)) cout << "find 3" << endl;
    	else cout << "can not find 3" << endl;
    	printTree(root);
    	remove(root,15);
    	printTree(root);
    	return 0;
    };
    

    结果:

    参考资料

  • 相关阅读:
    个人阅读作业Week7
    2015年团队项目选择
    实验与作业(Python)-02 Python函数入门与温度转换程序(函数、input、eval、int、float、列表)
    实验与作业(Python)-03 Python程序实例解析(函数、循环、range、turtle)
    实验与作业(Python)-04 数据类型、数学函数与字符串
    Java第05次实验提纲(Java图形界面编程)
    Python能做些什么?
    Python教学相关资料
    使用邮件交流的好处
    Java9相关资料(JShell简易教程等)
  • 原文地址:https://www.cnblogs.com/multhree/p/10510383.html
Copyright © 2011-2022 走看看