码迷,mamicode.com
首页 > 其他好文 > 详细

二叉搜索树

时间:2021-02-16 11:53:34      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:define   情况   tmp   static   实现   public   key   size_t   月初   

今天是正月初一,也是只能默默的在这里写博客,情绪烦乱,刷题老是走神,最后决定写点博客来巩固一下之前所学,让自己放几天假,春节的张灯结彩,热闹非凡似乎与我格格不入,让这二叉搜索树陪我熬过去吧,那么我们来看二叉搜索树的ADT。

 

#ifndef BinarySearchTree_H
#define BinarySearchTree_H

struct TreeNode;
typedef struct TreeNode *Position;
typedef struct TreeNode *SearchTree;

SearchTree MakeEmpty(SearchTree T);
Position   Find(ElementType X, SearchTree T);
Position   FindMax(SearchTree T);
Position   FindMin(SearchTree T);
SearchTree Insert(ElementType X, SearchTree T);
SearchTree Delete(ElementType X, SearchTree T);

#endif  /*BinarySearchTree_H*/

 

 

 当然我们还缺少一个TreeNode的定义,我们讲该定义放在一个头文件中,并包含进去,TreeNode定义如下

 1 #ifndef _TREENODE_H
 2 #define _TREENODE_H
 3 
 4 typedef int ElementType;
 5 
 6 struct TreeNode{
 7     ElementType val;
 8     struct TreeNode *left;
 9     struct TreeNode *right;
10 };
11 
12 #endif  /*_TREENODE_H*/

 

 

我们可以看到,我们typedef了一个ElementType,因为C语言没有模板,所以我们选择这么做,在最后,我会给出C++的完整代码,前半部分我们主要用C语言实现,C++的实现大部分与C语言的实现相同。

1. Find操作

Find操作返回的是树中具有关键字X的节点指针,不存在则返回NULL。这个操作很简单,如果当前节点是NULL,返回NULL,如果当前节点的关键字大于X,在左子树种查找,否则在右子树中查找,如果等于则返回当前节点。此操作时间复杂度为O(logn)

 1 Position Find(ElementType X, SearchTree T)
 2 {
 3     if(T == NULL)
 4         return NULL;
 5     if(X < T->val)
 6         return Find(X, T->left);
 7     else if(X > T->val)
 8         return Find(X, T->right);
 9     else
10         return T;
11 }

 

 

2. FindMin和FindMax

这两个函数返回树的最大最小值的位置,复杂度同样为O(logn)

1 Position FindMin(SearchTree T)
2 {
3     if(T == NULL)
4         return NULL;
5     else if(T->left == NULL)
6         return T;
7     else
8         return FindMin(T->left);
9 }
1 Position FindMax(SearchTree T)
2 {
3     if(T == NULL)
4         return NULL;
5     else if(T->right == NULL)
6         return T;
7     else
8         return FindMax(T->right);
9 }

 

3. Insert

Insert操作总是先执行一遍类似于Find操作的过程,知道Position下降到叶节点,再叶节点的left或right新建一个TreeNode。复杂度同样为O(logn)

 1 SearchTree Insert(ElementType X, SearchTree T)
 2 {
 3     if(T == NULL){
 4         T = (struct TreeNode)malloc(sizeof(struct TreeNode));
 5         T->val = X;
 6         T->left = T->right = NULL;
 7     }
 8     else if(X < T->val)
 9         T->left =  Insert(X, T->left);
10     else if(X > T->val)
11         T->right = Insert(X, T->right);
12     return T;
13 }

 

 

4.Delete

Delete是所有操作里最复杂的一个,需要分3种情况讨论,如果是树叶,可以直接删除,如果只有一个子节点,可以通过调整指针绕过当前节点来删除,如果有两个孩子,我们选择右子树最小的节点移到当前节点,再转化为第二情况。复杂度O(logn),这步操作强烈建议用递归写,迭代比较困难。

 1 SearchTree Delete(ElementType X, SearchTree T)
 2 {
 3     Position Tmp;
 4     
 5     if(T == NULL)
 6         return NULL;
 7     else if(X < T->val)
 8         T->left = Delete(X, T->left);
 9     else if(X > T->val)
10         T->right = Delete(X, T->right);
11     else if(T->left && T->right){
12         Tmp = FindMin(T->right);
13         T->val = Tmp->val;
14         T->right = Delete(Tmp->val, T->right);
15     }
16     else{
17         Tmp = T;
18         if(T->left == NULL)
19             T = T->right;
20         else if(T->right == NULL)
21             T = T->left;
22         free(Tmp);
23     }
24 }

 

 

5.MakeEmpty

这个操作我们选择用后序遍历的方式进行(后序遍历应该不用多说)

1 SearchTree MakeEmpty(SearchTree T)
2 {
3     if(T != NULL){
4         MakeEmpty(T->left);
5         MakeEmpty(T->right);
6         free(T);
7     }
8     return NULL;
9 }

 

 

虽然上述所有操作平均都是O(logn),但是在某些特殊情况下将退化为O(n),我们可以引入Rotate这一概念来消除,这是平衡树的内容,我们到以后再细讲,但看了这些可能你们还是决定实际种用不到,下面给出一个我已经包装好的模板。

TreeNode.h

#ifndef TREENODE_H
#define TREENODE_H

#include <cstdio>

template<class ElementType>
struct TreeNode{
	ElementType val;
	TreeNode* left;
	TreeNode* right;
	TreeNode():left(NULL), right(NULL){}
	TreeNode(ElementType value):val(value), left(NULL), right(NULL){}
	TreeNode(ElementType value, TreeNode* l, TreeNode* r) :
		val(value), left(l), right(r){}
};

#endif

  

BST.h

#include "TreeNode.h"

#ifndef _TREE_H
#define _TREE_H

typedef unsigned size_type;

template<class T>
class BST{
	public:
		BST():size(0), root(NULL){}
		~BST();
		void clear();
		TreeNode<T> *Find(T key);
		bool empty();
		size_type Size();
		bool Insert(T key);
		void erase(T key);
		TreeNode<T>* Delete(T key, TreeNode<T> *Node);
		TreeNode<T>* FindMin(TreeNode<T>* Node) const;
		TreeNode<T>* FindMax(TreeNode<T>* Node) const;
		void Print(void(*operation)(TreeNode<T>*)) const;
	private:
		size_type size;
		TreeNode<T> *root;
		static void(*Operation)(TreeNode<T>*);
		void inorder(TreeNode<T>* Node) const;
		void postorder(TreeNode<T>* Node) const;
		void preorder(TreeNode<T>* Node) const;
};

#endif

  

BST.cpp

#include "BST.h"
#include <cstdlib>

template<class T>
void Del(TreeNode<T> *Node)
{
	if(Node != NULL){
		delete Node;
		Node = NULL;
	}
}

template<class T>
void (* BST<T>::Operation)(TreeNode<T> *) = NULL;

template<class T>
TreeNode<T>* BST<T>::Find(T key)
{
	TreeNode<T> *np = root;
	while(np != NULL){
		if(np->val < key)
			np = np->right;
		else if(np->val > key)
			np = np->left;
		else
			return np;
	}
	return NULL;
}

template<class T>
BST<T>::~BST<T>()
{
	if(root != NULL)
		this->clear();
}

template<class T>
void BST<T>::clear()
{
	Operation = Del;
	postorder(root);
	root = NULL;
	size = 0;
}

template<class T>
size_type BST<T>::Size()
{
	return size;
}

template<class T>
bool BST<T>::empty()
{
	return size == 0;
}

template<class T>
bool BST<T>::Insert(T key)
{
	TreeNode<T> *np = root, *pp;//pp is the mark point.
	while(np != NULL){
		pp = np;
		if(np->val < key)
			np = np->right;
		else if(np->val > key)
			np = np->left;
		else
			return 0;
	}
	size++;
	if(root == NULL){
		root = new TreeNode<T>(key);
		return 1;
	}
	else{
		np = new TreeNode<T>(key);
		if(pp->val > key)
			pp->left = np;
		else
			pp->right = np;
			return 1;
	}
}


template<class T>
TreeNode<T>* BST<T>::FindMin(TreeNode<T> *Node) const
{
	if(Node != NULL){
		TreeNode<T> *np = Node, *pp;
		while(np != NULL){
			pp = np;
			np = np->left;
		}
		return pp;
	}
	return NULL;
}

template<class T>
TreeNode<T>* BST<T>::FindMax(TreeNode<T> *Node) const
{
	if(Node != NULL){
		TreeNode<T> *np = Node, *pp;
		while(np != NULL){
			pp = np;
			np = np->right;
		}
		return pp;
	}
	return NULL;
}

template<class T>
void BST<T>::Print(void(*operation)(TreeNode<T>*)) const
{
	Operation = operation;
	inorder(root);
}

template<class T>
void BST<T>::inorder(TreeNode<T> *Node) const
{
	if(Node != NULL){
		inorder(Node->left);
		Operation(Node);
		inorder(Node->right);
	}
}

template<class T>
void BST<T>::postorder(TreeNode<T> *Node) const
{
	if(Node != NULL){
		postorder(Node->left);
		postorder(Node->right);
		Operation(Node);
	}
}

template<class T>
void BST<T>::preorder(TreeNode<T> *Node) const
{
	if(Node != NULL){
		Operation(Node);
		preorder(Node->left);
		preorder(Node->right);
	}
}

template<class T>
void BST<T>::erase(T key)
{
	this->root = Delete(key, this->root);
}

template<class T>
TreeNode<T>* BST<T>::Delete(T key, TreeNode<T> *Node)
{
	TreeNode<T> *tmpcell;
	if(Node == NULL)
		return NULL;
	else if(Node->val < key)
		Node->right = Delete(key, Node->right);
	else if(Node->val > key)
		Node->left = Delete(key, Node->left);
	else if(Node->left != NULL && Node->right != NULL){
		tmpcell = FindMin(Node->right);
		Node->val = tmpcell->val;
		Node->right = Delete(tmpcell->val, Node->right);
	}
	else{
		tmpcell = Node;
		if(Node->right == NULL)
			Node = Node->left;
		else if(Node->left == NULL)
			Node = Node->right;
		delete tmpcell;
		size--;
	}
	
	return Node;
}

  

觉得有用就拿区别,干饭干饭,走起,拜拜ヾ(?ω?`)o

二叉搜索树

标签:define   情况   tmp   static   实现   public   key   size_t   月初   

原文地址:https://www.cnblogs.com/JCKeep/p/14398612.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!