zoukankan      html  css  js  c++  java
  • 简述数据结构:二叉查找树

    二叉查找树的性质

    当一棵二叉树满足下面条件的时候就成了二叉查找树:对于树的任意一个节点,左儿子的值比右儿子小(或者反过来也行)。
    二叉查找树本质还是二叉树,因此也具有二叉树的性质。

    二叉查找树的操作

    1. 判断某元素是否在树中:contains

    这个操作比较简单,递归查找树根.

    //公有函数contains通过调用私有函数contains递归查找。
    bool contains(const Object &e) const
    {
        return contains(e, root);
    }
    
    bool contains(const Object &e, Node *t)
    {
        if(t == NULL)
            return false;
    
        if(e < t->element)
            return contains(e, t->left);
        else if(t->element < e)
            return contains(e, t->right);
        else
            return true;
    }
    

    2. 插入一个元素:insert

    往一个二叉查找树中插入元素不会改变原树的结构,只需要找到一个合适的位置满足二叉查找树的性质就可以了。

    void insert(const Object &e)
    {
        insert(e, root);
    }
    //私有函数操作子树,二叉查找树的插入操作不会改变原树的结构
    void insert(const Object &e, Node *&t)
    {
        //空子树
        if(t == NULL)
        {
            t = new Node(e,NULL,NULL);
        }
        else
        {
            if(e < t->element)
                insert(e, t->left);
            else if(t->element < e)
                insert(e, t->right);
            else
                ;
        }
    }
    

    3. 删除一个元素:remove

    删除一个元素必须分情况来讨论。

    1. 要删除的节点是叶子。
      如果要删除的节点是一个叶子,那么只需要简单地删除这个节点,并将其父节点的相关指针置为NULL就可以了,具体的做法是直接将这个节点的指针变为NULL,然后释放其存储。
    2. 要删除的节点只有一个子树。
      如果要删除的节点只有一个子树,那么只需要让该节点的父节点指向节点的子树,然后释放掉该节点的存储。
    3. 要删除的节点有两个子树。
      如果要删除的节点有两个子树,那么需要找出该节点右子树中的最小元素,并将这个最小元素赋给本节点,再将右子树中的该元素删除,此时的删除操作就转化成了1中情况(最小元素必为叶子)。

    其中,上述1和2可以合并实现。

    void remove(const Object &e)
    {
        remove(e, root);
    }
    void remove(const Object &e, Node *&t)
    {
        if(t == NULL)
            return;
    
        //未找到元素e,于是递归查找
        if(e < t->element)
            remove(e, t->left);
        else if(t->element < e)
            remove(e, t->right);
        //找到元素e
        else if(t->left != NULL && t->right != NULL) //有两个子节点
        {
            t->element = findMin(t->right);
            remove(t->element, t->right);
        }
        else
        {
            Node *old = t;
            t = (t->left != NULL)? t->left : t->right;
            delete old;
        }
    }
    

    二叉查找树C++实现

    template <typename Object>
    class BinarySearchTree
    {
    	public:
    		BinarySearchTree():root(NULL){}
    		BinarySearchTree(BinarySearchTree &t)
    		{
    			root = t;  //浅拷贝
    		}
    		~BinarySearchTree()
    		{
    			makeEmpty();
    		}
    	
    		//深拷贝
    		BinarySearchTree & operator =(BinarySearchTree &t)
    		{
    			if(root == t)
    				return;
    			if(root != NULL)
    				makeEmpty();
    			root = clone(root);
    		}
    
    		void insert(const Object &e)
    		{
    			insert(e, root);
    		}
    		void remove(const Object &e)
    		{
    			remove(e, root);
    		}
    		bool contains(const Object &e) const
    		{
    			return contains(e, root);
    		}
    		bool isEmpty() const
    		{
    			return root == NULL;
    		}
    
    		const Object & findMin() const
    		{
    			return findMin(root);
    		}
    		const Object & findMax() const
    		{
    			return findMax(root);
    		}
    
    		void makeEmpty()
    		{
    			makeEmpty(root);
    		}
    
    		void printTree()
    		{
    			printTree(root);
    			std::cout<<"--------------"<<std::endl;
    		}
    	private:
    		struct Node
    		{
    
    			Object element;
    			Node *left;
    			Node *right;
    			Node(const Object &ele, Node *l, Node *r):element(ele),left(l),right(r){}
    		};
    
    		Node *root;
    		
    		//私有函数操作子树,二叉查找树的插入操作不会改变原树的结构
    		void insert(const Object &e, Node *&t)
    		{
    			//空子树
    			if(t == NULL)
    			{
    				t = new Node(e,NULL,NULL);
    			}
    			else
    			{
    				if(e < t->element)
    					insert(e, t->left);
    				else if(t->element < e)
    					insert(e, t->right);
    				else
    					;
    			}
    		}
    
    		void remove(const Object &e, Node *&t)
    		{
    			if(t == NULL)
    				return;
    
    			//未找到元素e,于是递归查找
    			if(e < t->element)
    				remove(e, t->left);
    			else if(t->element < e)
    				remove(e, t->right);
    			//找到元素e
    			else if(t->left != NULL && t->right != NULL) //有两个子节点
    			{
    				t->element = findMin(t->right);
    				remove(t->element, t->right);
    			}
    			else
    			{
    				Node *old = t;
    				t = (t->left != NULL)? t->left : t->right;
    				delete old;
    			}
    			
    
    		}
    
    		bool contains(const Object &e, Node *t)
    		{
    			if(t == NULL)
    				return false;
    
    			if(e < t->element)
    				return contains(e, t->left);
    			else if(t->element < e)
    				return contains(e, t->right);
    			else
    				return true;
    
    		}
    
    		const Object & findMin(Node *t) const
    		{
    			while(t->left != NULL)
    			{
    				t = t->left;       //查找最左边的元素
    			}
    
    			return t->element;
    		}
    	
    		const Object & findMax(Node *t) const
    		{
    			while(t->right != NULL)
    			{
    				t = t->right;     //查找最右边的元素
    			}
    
    			return t->element;
    		}
    
    		void makeEmpty(Node * &t)
    		{
    			if(t != NULL)
    			{
    				makeEmpty(t->left);
    				makeEmpty(t->right);
    				delete t;
    			}
    			 t = NULL;
    		}
    
    		Node * clone(Node *t)
    		{
    			if(t == NULL)
    				return;
    			
    			return new Node(t->element, t->left, t->right);	
    
    		}
    
    		void printTree(const Node *t)
    		{
    			if(t == NULL)
    				return;
    			std::cout<<t->element<<std::endl;
    			if(t->left != NULL)
    				printTree(t->left);
    			if(t->right != NULL)
    				printTree(t->right);
    		}
    };
    
    
  • 相关阅读:
    [2018福大至诚软工助教]原型设计+用户规格说明书小结
    高等数理逻辑大作业
    [2018福大至诚软工助教]测试与优化小结
    [2018福大至诚软工助教]结对项目小结
    BETA 版冲刺前准备
    Alpha冲刺之事后诸葛亮
    Alpha 冲刺 (10/10)
    Alpha 冲刺 (9/10)
    Alpha 冲刺 (8/10)
    Alpha 冲刺 (7/10)
  • 原文地址:https://www.cnblogs.com/jaletech/p/3903347.html
Copyright © 2011-2022 走看看