二叉排序树
二叉查找树
1.概念
二叉排序树可以是一颗空树,或者是具有以下性质的树:
1.左子树如果不为空,左子树上所有节点的值均小于等于根节点的值
2.右子树如果不为空。右子树上所有节点的值均大于等于根节点的值
3.左右子树均为二叉排序树
2.实现
我们讨论二叉树的查找,插入,删除,遍历,线索化。
#ifndef BST_H #define BST_H #include <iostream> using namespace std; template<typename T> class Node { public: T Data; Node *LeftChild; Node *RightChild; Node(const T& data) : Data(data), LeftChild(nullptr), RightChild(nullptr){} }; template<typename T> class BST { public: BST() : Root(nullptr){} ~BST(){ this->clear(); } void clear() { this->clear(Root); } bool isEmpty() const{ return Root == nullptr; } void preorder(){//先序遍历 preorder(Root); } void inorder(){//中序遍历 inorder(Root); } void postorder(){//后序遍历 postorder(Root); } T* search(const T&el) const{ return search(root,el); } void breadthFirst(); void iterativePreorder();//非递归先序 void iterativeInorder(); void iterativePostorder(); void insert(const T&); void erase(Node<T> *&); private: Node<T>* Root; void clear(Node<T>* node); void preorder(Node<T>* node); void inorder(Node<T>* node); void postorder(Node<T>* node); T* search(Node<T>* node,const T&el) const; void visit(Node<T> *p){ cout << p->Data << endl; } };
1.查找
根据二叉排序树的概念,将查找值与树的节点比较,
如果要查找的值小于节点的值,转向节点的左子树,
如果要查找的值大于节点的值,转向节点的右子树。
如果二者相同,则查找成功。
template<typename T> T* BST::search(Node<T>* node,const T&el) const { while(node) if(el == node->Data) return &node->Data; else if(el < node->Data) return node->LeftChild; else return node->RightChild; return nullptr; }
2.树的广度优先遍历
广度优先遍历,是指从最高层(或者最底层)开始,向下(或者向上)逐层的访问每个节点,在每个层次上,从左到右(或者从右到左)访问每个节点
。所以实际上,我们有四种不同的广度优先遍历方式。我们来完成从上到下,从左到右的广度优先遍历的实现。
template<typename T> void BST::breadthFirst() { std::queue<Node<T>*> nodeQueue; Node<T>* p = Root; if(p) { nodeQueue.push(p); while(!nodeQueue.empty()) { p = nodeQueue.front(); nodeQueue.pop(); visit(p); if(p->LeftChild) nodeQueue.push(p->LeftChild); if(p->RightChild) nodeQueue.push(p->RightChild); } } }
3.树的深度优先遍历的递归实现。
深度优先遍历分为三种:
1.先序遍历:先访问根节点,再访问左子树,右子树。访问子树时同样先访问子树的根节点,再访问子树的左子树,右子树。
2.中序遍历:先访问左子树,再访问根节点,最后访问右子树。
3.后序遍历:先访问左子树,再访问右子树,最后访问根节点。
使用递归我们可以写出非常清晰明了的函数来实现树的深度遍历
template<typename T> void BST::preorder(Node<T>* p) { if(p) { visit(p); preorder(p->LeftChild); preorder(p->RightChild); } } template<typename T> void BST::inorder(Node<T>* p) { if(p) { inorder(p->LeftChild); visit(p); inorder(p->RightChild); } } template<typename T> void BST::postorder(Node<T>* p) { if(p) { postorder(p->LeftChild); postorder(p->RightChild); visit(p); } }
我们在函数中使用了双重递归,这对系统造成了沉重的负担。我们希望可以写出非递归版本的深度优先遍历函数。
4.树的深度优先遍历的非递归实现