初级木遁忍术‘树界降临’掌握完毕。
一心追逐无上忍术的我,准备学习进阶的忍术 木遁-森罗万象!
------------------ switch -------------------
中级篇
综述二叉查找树的类框架及各种眼花缭乱的DFS递归。
二叉树类的逻辑思维要求较高,细节要求较严谨。 此篇代码大部摘自著作 《数据结构与算法分析 C++描述》。 此类通过公有函数对私有函数的调用及私有函数的递归运用,巧妙实现了二叉树的构建,查找,删除等功能。
以下是代码框架。后续给出部分私有函数的实现代码,详细参见原著。
1 //类模板需支持比较运算符 2 template <typename Comparable> 3 class BinarySearchTree 4 { 5 private: 6 struct BinaryNode 7 { 8 Comparable element; 9 BinaryNode* left; 10 BinaryNode* right; 11 BinaryNode(const Comparable& _el = Comparable(), BinaryNode* _le = NULL, BinaryNode* _ri = NULL) 12 :element(_el), left(_le), right(_ri) {} 13 }; 14 public: 15 //三大函数 16 BinarySearchTree() {} 17 BinarySearchTree(const BinarySearchTree& rhs) 18 { 19 if (this != &rhs) *this = rhs; 20 } 21 BinarySearchTree operator = (const BinarySearchTree& rhs) 22 { 23 if (this != &rhs) 24 { 25 makeEmpty(); 26 root = clone(rhs.root); 27 } 28 return *this; 29 } 30 //析构函数 31 ~BinarySearchTree() { makeEmpty(); } 32 //求最小值 33 const Comparable& findMin() const 34 { 35 return findMin(root)->element; 36 } 37 //求最大值 38 const Comparable& findMax() const 39 { 40 return findMax(root)->element; 41 } 42 //是否含有指定元素 43 bool contains(const Comparable& t) const 44 { 45 contains(t, root); 46 } 47 //插入指定元素 48 void insert(const Comparable& t) 49 { 50 insert(t, root); 51 } 52 //删除指定元素 53 void remove(const Comparable& t) 54 { 55 remove(t, root); 56 } 57 //打印树(默认中序遍历/inorder traversal) 58 void printTree() const 59 { 60 printTree(root); 61 } 62 //是否为空树 63 bool isEmpty() const 64 { 65 return root == NULL ? true : false; 66 } 67 //删除树 68 void makeEmpty() 69 { 70 makeEmpty(root); 71 } 72 private: 73 BinaryNode* root; //根节点 74 // ... ... private methods ... ... 75 };
简略讲下私有函数bool contains(const Comparable& x, BinaryNode* t) const 的递归调用。
递归代码的简洁性有时会让刚接触递归的人感到迷惑,其实并不难理解。
程序以 t == NULL 为递归界限,进行DFS。若不符合条件,调用递归函数。
代码如下。
1 bool contains(const Comparable& x, BinaryNode* t) const 2 { 3 if (t == NULL) return false; 4 else if (t->element > x) return contains(x, t->right); 5 else if (t->element < x) return contains(x, t->left); 6 else return true; //找到 x 7 }
十分简洁,下面是其他私有函数的实现。
1 void insert(const Comparable& x, BinaryNode*& t) 2 { 3 if (t == NULL) t = new BinaryNode(x); 4 else if (t->element > x) insert(x, t->right); 5 else if (t->element < x) insert(x, t->left); 6 else //树中存在待插入的元素 7 ; 8 } 9 void remove(const Comparable& x, BinaryNode*& t) 10 { 11 if (t == NULL) return; //树为空或者(递归到叶结点)不存在待删除的元素时 12 if (t->element > x) remove(x, t->right); 13 else if (t->element < x) remove(x, t->left); 14 else if (t->left != NULL && t->right != NULL) //找到待删除的结点,且有两个子树 15 { 16 t->element = findMin(t->right)->element; 17 remove(t->element, t->right); //该步骤可以写一个void removeMin(const Comparable& x,BinaryNode*)函数提高效率 18 /*void removeMin(const Comparable& x,BinaryNode* t) 19 { 20 if (t == NULL) return; 21 if (t->left == NULL) 22 { 23 BinaryNode* oldNode = t; 24 t = (t->left == NULL) ? t->left : t->right; 25 delete oldNode; 26 } 27 else removeMin(t->left); //若未找到 28 }*/ 29 30 } 31 else //找到待删除的结点,只有一个子树 32 { 33 BinaryNode* oldNode = t; 34 t = (t->left != NULL) ? t->left : t->right; 35 delete oldNode; 36 } 37 } 38 BinaryNode* findMin(BinaryNode* t) const 39 { 40 //循环版本 41 //if(t) 42 // while (t->left) t = t->left; 43 //return t; 44 45 //递归 46 if (t == NULL) return NULL; 47 if (t->left == NULL) return t; 48 return findMin(t->left); 49 }
可以注意到insert和remove的传递参数是指针的引用,而findMin则是传递指针。
这细微的"Shitf + 7"的区别,是值得细细品味的。