• 二叉搜索树


    二叉搜索树(Binary Search Tree)也叫做二叉排序树或者二叉查找树。顾名思义,它是一种对排序和查找都很有用的特殊二叉树

    二叉查找树满足以下性质:(假设二叉查找树中每个节点元素都是不同的,它也可以为空)

    1. 非空左子树的所有键值小于其根节点的键值;
    2. 非空右子树的所有键值大于其根节点的键值;
    3. 左,右两棵子树都是二叉搜索树

    二叉搜索树本质上还是一棵二叉树,只不过对它做了限定,就行队列和栈一样,它们是对线性表做了限制。对二叉搜索树的遍历和创建操作与普通二叉树一致。但是二叉搜索树的特点使得对它的查找,插入,删除变得有些不同。

    二叉搜索树的平均深度是O(logn)的,一般不会造成爆栈的。

    二叉搜索树的对于查找问题的解决,本质上还是二分法的使用。但是不同于我们对一个有序数组使用的二分查找法。有序数组上施加的二分查找是元素个数恒定不变的(不进行插入和删除操作),称之为静态查找。二叉搜索树则可以支持插入和删除操作,它使得查找的范围可以动态变化,称之为动态查找

    如果按照查找操作是如何进行的来分类,那么二叉搜索树和二分查找都是基于比较实现的;另外一种实现查找的方式是基于映射实现的,即:散列表,或者称之为哈希表。

    二叉搜索树的ATD和操作集

    #ifndef BST
    #define BST
    
    #include<iostream>
    #include<stack>
    
    using std::cout;
    using std::cin;
    using std::stack;
    
    typedef struct TreeNode Tree;
    typedef Tree * PTree;
    typedef PTree Position;
    typedef int ElementType;
    
    struct TreeNode
    {
    	ElementType data;
    	PTree left;
    	PTree right;
    };
    Position Find(ElementType k, PTree T);		 //递归版查找
    Position Find(ElementType k, PTree T,int a); //迭代版查找
    Position FindMax(PTree T);					 //返回最大元素
    Position FindMin(PTree T);					 //返回最小元素
    void InorderTraversal(PTree T);				 //递归版中序遍历
    void InorderTraversal(PTree T,int a);		 //迭代版中序遍历
    PTree Insert(ElementType x, PTree T);		 //插入操作
    PTree Delete(ElementType x, PTree T);		 //删除操作
    int PostinorderGetHeight(PTree T);			 //二叉树的高度
    
    #endif // !BST

    二叉搜索树操作集的C++实现代码:

    #include "searchtree.h"
    
    //递归版本实现的查找函数,二叉树的平均深度是O(log n),可以递归的
    Position Find(ElementType k, PTree T)
    {
    	if (NULL == T)
    	{
    		return NULL;			//空树
    	}
    	if (k < T->data)			//k小于data,去该节点的左子树查找。
    	{
    		return Find(k,T->left);
    	}
    	else if (k > T->data)		//k大于data,去该节点的右子树查找。
    	{
    		return Find(k, T->right);
    	}
    	else if (k == T->data)		//k等于data,直接返回该节点。
    	{
    		return T;
    	}
    }
    
    Position Find(ElementType k, PTree T, int a)
    {
    	while (T)		//树不空执行循环
    	{
    		if (k > T->data)
    		{
    			T = T->right;		//转右子树查找
    		}
    		else if (k < T->data)
    		{
    			T = T->left;		//转左子树查找
    		}
    		else
    		{
    			return T;			//找到了该元素
    		}
    	}
    	return NULL;	//没有找到该元素
    }
    
    Position FindMax(PTree T)
    {
    	if (NULL == T)
    	{
    		return NULL;	//空树
    	}
    	else
    	{
    		while (T->right)
    		{
    			T = T->right;		//最大值在其右子树上,且该右子树无右子树
    		}
    		return T;			//返回最大值所在节点
    	}
    }
    
    Position FindMin(PTree T)
    {
    	if (NULL == T)
    	{
    		return NULL;	//空树
    	}
    	else
    	{
    		while (T->left)
    		{
    			T = T->left;		//最小值在其左子树上,且该左子树无左子树
    		}
    		return T;			//返回最小值所在节点
    	}
    }
    
    void InorderTraversal(PTree T)
    {
    	if (T)
    	{
    		InorderTraversal(T->left);
    		cout << T->data << ' ';
    		InorderTraversal(T->right);
    	}
    }
    
    void InorderTraversal(PTree T, int a)
    {
    	if (NULL == T)
    	{
    		return;
    	}
    	else
    	{
    		stack<PTree> S;			//创建空栈
    		while (T || !S.empty())
    		{
    			while (T)
    			{
    				S.push(T);				//将T压入栈中
    				T = T->left;			//转左子树
    			}
    			if(!S.empty())
    			{
    				/*T = (PTree)malloc(sizeof(Tree));
    				T->data = S.top()->data;
    				T->left = S.top()->left;
    				T->right = S.top()->right;*/
    				T = S.top();
    				cout << T->data << ' ';
    				T = T->right;            //转右子树
    				S.pop();				//删除栈顶元素
    			}
    		}
    	}
    }
    
    PTree Insert(ElementType x, PTree T)
    {
    	PTree temp = NULL;
    	PTree BT = T;
    	if (!T)
    	{
    		T = (PTree)malloc(sizeof(Tree));
    		T->data = x;
    		T->left = T->right = NULL;
    		return T;
    	}
    	else
    	{
    		while (T)
    		{
    			if (x < T->data)
    			{
    				if (!T->left)	//若左子树为空,插入到这里
    				{
    					temp = (PTree)malloc(sizeof(Tree));
    					temp->data = x;
    					temp->left = NULL;
    					temp->right = NULL;
    					T->left = temp;
    					break;
    				}
    				else			//若不空,转左子树
    				{
    					T = T->left;
    				}
    			}
    			if (x > T->data)
    			{
    				if (!T->right)		//若右子树为空,插入到这里
    				{
    					temp = (PTree)malloc(sizeof(Tree));
    					temp->data = x;
    					temp->left = NULL;
    					temp->right = NULL;
    					T->right = temp;
    					break;
    				}
    				else		//若不空,转右子树
    				{
    					T = T->right;
    				}
    			}
    			if (x == T->data)	//找到这个元素
    			{
    				break;
    				//如果要插入的元素已经在该树中存在,那么一般有两种做法
    				//1.什么操作也不做,适合在不追求重复元素的场合使用
    				//2.向树的ADT中增加一个域,用来保存该元素的出现次数。这样使得树
    				//增加了一下附加空间,但是,却比将重复信息放入树中好的多,这样避免
    				//了树深度的增加。
    				//在这里我们采用第一种方式,什么也不做。
    			}
    		}
    		return BT;
    	}
    }
    
    PTree Delete(ElementType x, PTree T)
    {
    	PTree temp;
    	if (!T)
    	{
    		cout << "删除元素未找到!
    ";
    	}
    	else
    	{
    		if (x < T->data)
    		{
    			T->left = Delete(x, T->left);		//递归删除左子树
    		}
    		else if (x > T->data)
    		{	
    			T->right = Delete(x, T->right);		//递归删除右子树
    		}
    		else
    		{
    			if (T->left && T->right)	//左右子树都存在
    			{
    				temp = FindMin(T->right);
    				//temp = FindMax(T->left);
    				T->data = temp->data;
    				T->right = Delete(T->data, T->right);
    			}
    			else            
    			{
    				temp = T;
    				if (!T->left)        //右子树存在或者左右子树都不存在
    				{
    					T = T->right;
    				}
    				else if (!T->right)    //左子树存在或者左右子树都不存在
    				{
    					T = T->left;
    				}
    				free(temp);
    			}
    			return T;
    		}
    	}
    }
    
    int PostinorderGetHeight(PTree T)
    {
    	if (T)
    	{
    		int l, r, max;
    		l = PostinorderGetHeight(T->left);
    		r = PostinorderGetHeight(T->right);
    		max = l > r ? l : r;
    		return max + 1;
    	}
    	else
    	{
    		return 0;
    	}
    }
    

    main.cpp文件

    #include"searchtree.h"
    
    int main()
    {
    	PTree BT = NULL;
    	for (int i = 5; i < 10; i++)	//把根节点设置为5,插入5-9;
    	{
    		BT = Insert(i, BT);
    	}
    	for (int i = 0; i < 5; i++)		//插入0-4.
    	{
    		BT = Insert(i, BT);
    	}
    	Insert(5, BT);
    	//理论上中序遍历输出应该是0 1 2 3 4 5 6 7 8 9
    	cout << "中序遍历输出:";
    	InorderTraversal(BT,1);
    	cout << "
    树的深度是:";
    	cout << PostinorderGetHeight(BT);
    	cout << "
    树中最大元素是:" << FindMax(BT)->data;
    	cout << "
    树中最小元素是:" << FindMin(BT)->data;
    	cout << '
    ' << "删除元素5后,中序遍历结果:";
    	BT = Delete(5, BT);
    	InorderTraversal(BT);
    	cout << '
    ';
    	PTree temp;
    	cout << "查找5这个元素的结果:";
    	temp = Find(5, BT);
    	if (NULL == temp)
    	{
    		cout << "未找到!
    ";
    	}
    	else
    	{
    		cout << temp->data << '
    ';
    	}
    	cout << "查找3这个元素的结果:";
    	temp = Find(3, BT);
    	if (NULL == temp)
    	{
    		cout << "未找到!
    ";
    	}
    	else
    	{
    		cout << temp->data << '
    ';
    	}
    
    	system("pause");
    	return 0;
    }

    运行结果:

  • 相关阅读:
    理解jquery的$.extend()、$.fn和$.fn.extend()
    Angularjs,WebAPI 搭建一个简易权限管理系统
    ASP.NET MVC Boilerplate简介
    写jQuery插件
    给Asp.Net MVC及WebApi添加路由优先级
    Oracle数据库之开发PL/SQL子程序和包
    Git 1.9.5.msysgit.1
    快速解读GC日志(转)
    Git & Github 一页简明笔记(转)main
    用python3.x与mysql数据库构建简单的爬虫系统(转)
  • 原文地址:https://www.cnblogs.com/zy666/p/10504287.html
Copyright © 2020-2023  润新知