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