标签: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