简述数据结构:二叉查找树

二叉查找树的性质

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

二叉查找树的操作

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);
		}
};

posted @ 2014-08-10 20:32  野风鼓瑟震山岗  阅读(255)  评论(0编辑  收藏  举报