二叉查找树类的C++实现
二叉查找树或者是一棵空树;或者是具有下列性质的二叉树: (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值; (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值; (3)左、右子树也分别为二叉排序树。
下面的二叉查找树类主要实现了二叉查找树的以下操作:查找结点、插入结点、构造二叉查找树、查找指定结点的前驱和后继、删除结点。
二叉查找树结点
template <typename T> struct BiNode{ T k_data; BiNode<T> *LChild, *RChild; BiNode<T> *Parent; BiNode(T element, BiNode<T> *lt, BiNode<T> *rt, BiNode<T> *pt):k_data(element), LChild(lt), RChild(rt), Parent(pt){} }; //打印节点 template <typename T> void PrintNode(BiNode<T> node) { cout<<node.k_data<<" "; }
二叉查找树类
template <typename T> class BiSearchTree { public: BiSearchTree(BiNode<T>* pRoot = NULL) { root = pRoot; } ~BiSearchTree() { ReleaseBiTree(&root); } void ReleaseBiTree(BiNode<T> **pRoot) { if (*pRoot != NULL) { ReleaseBiTree(&(*pRoot)->LChild); ReleaseBiTree(&(*pRoot)->RChild); delete (*pRoot); } } //前序遍历二叉树 void VisitBiTreePreOrder(void(*Visit)(BiNode<T>)) const { VisitBiTreePreOrder(root, Visit); } //后序遍历二叉树 void VisitBiTreeInOrder(void(*Visit)(BiNode<T>)) const { VisitBiTreeInOrder(root, Visit); } //查找,找到则返回节点,否则返回空 BiNode<T>* Search(T key) const { return Search(root, key); } //插入,如果已经有此节点,则返回false,否则插入节点,返回true bool Insert(T key) { BiNode<T>* p_newNode = new BiNode<T>(key, NULL, NULL, NULL); if (root == NULL)//空树 { root = p_newNode; } BiNode<T>* p = root; BiNode<T>* location = NULL;//key的插入位置 while(p != NULL)//查找key { location = p; if (p->k_data > key) { p = p->LChild; } else if(p->k_data < key) { p = p->RChild; } else { break; } } if (p == NULL)//未找到key { p_newNode->Parent = location; if (location->k_data > key) { location->LChild = p_newNode; } else if(location->k_data < key) { location->RChild = p_newNode; } return true; } else//找到key { return false; } } //创建二叉查找树 void CreatBiSearchTree(T a[], int n) { for (int i = 0; i < n; i++) { Insert(a[i]); } } //求一个节点的后继节点 BiNode<T>* bst_successor(BiNode<T> *node) { if (node->RChild != NULL)//右子树不为空,后继节点即为右子树的最小值节点 { BiNode<T>* p_node = node->RChild; while(p_node->LChild != NULL){p_node = p_node->LChild;} return p_node; } else//右子树为空,则那么node的直接后继节点就是从node向上的路径中第一次右转后遇到的节点。 { BiNode<T>* p_node = node->Parent; while(p_node != NULL && p_node->RChild == node) { node = p_node; p_node = p_node->Parent; } return p_node; } } //删除节点 //1. 结点Z没有孩子结点,那么直接删除Z就行了。 //2. 结点Z有一个孩子结点,那么删除Z,将Z的父结点与此孩子结点(子树)关联就可以了。 //3. 结点Z有两个孩子结点,实现方法就是将后继从二叉树中删除(适用第一、二种情况),将后继的数据覆盖到Z中。 bool Delete(T key) { if (root == NULL) { return false; } BiNode<T>* p = root; while(p != NULL)//查找key { if (p->k_data > key) { p = p->LChild; } else if(p->k_data < key) { p = p->RChild; } else { break; } } if (p != NULL)//查找到k { //求真正被删除的节点 BiNode<T>* p_real; if (p->LChild && p->RChild) p_real = bst_successor(p);//此真正被删除的节点一定满足条件1.或者条件2. else p_real = p; BiNode<T>* p_parent = p_real->Parent; if (p_real->LChild == NULL && p_real->RChild == NULL)//1.左右都空 { if (p_parent == NULL)//需要删除的是根节点 root = NULL; else if (p_parent->LChild == p_real) {p_parent->LChild = NULL;} else {p_parent->RChild = NULL;} } else if (p_real->LChild == NULL && p_real->RChild != NULL)//2.左空,右不空 { if (p_parent == NULL)//需要删除的是根节点 {root = p_real->RChild; p_real->RChild->Parent = NULL;} else if (p_parent->LChild == p_real) {p_parent->LChild = p_real->RChild; p_real->RChild->Parent = p_parent;} else {p_parent->RChild = p_real->RChild; p_real->RChild->Parent = p_parent;} } else if (p_real->LChild != NULL && p_real->RChild == NULL)//3.左不空,右空 { if (p_parent == NULL)//需要删除的是根节点 {root = p_real->LChild; p_real->LChild->Parent = NULL;} else if (p_parent->LChild == p_real) {p_parent->LChild = p_real->LChild; p_real->LChild->Parent = p_parent;} else {p_parent->RChild = p_real->LChild; p_real->LChild->Parent = p_parent;} } if (p_real != p)//如果是有双子树的节点,则覆盖原应被删除节点 { p->k_data = p_real->k_data; } delete p_real;//删除节点 return true; } return false; } protected: private: //查找节点 BiNode<T>* Search(BiNode<T>* pRoot, T key) const { if (pRoot == NULL) { return NULL;//查找失败 } if (pRoot->k_data == key) { return pRoot;//查找成功 } else if (pRoot->k_data > key) { return Search(pRoot->LChild, key); } else if(pRoot->k_data < key) { return Search(pRoot->RChild, key); } } void VisitBiTreePreOrder(BiNode<T> *pRoot, void(*Visit)(BiNode<T>)) const { if (pRoot != NULL) { Visit(*pRoot); VisitBiTreePreOrder(pRoot->LChild, Visit); VisitBiTreePreOrder(pRoot->RChild, Visit); } } void VisitBiTreeInOrder(BiNode<T> *pRoot, void(*Visit)(BiNode<T>)) const { if (pRoot != NULL) { VisitBiTreeInOrder(pRoot->LChild, Visit); Visit(*pRoot); VisitBiTreeInOrder(pRoot->RChild, Visit); } } BiNode<T> *root; };
测试代码
int main() { int keys[] = {8, 5, 2, 1, 4, 7, 3, 6, 9}; BiSearchTree<int>* p_BiSearchTree = new BiSearchTree<int>(); p_BiSearchTree->CreatBiSearchTree(keys, sizeof(keys)/sizeof(keys[0])); cout<<"前序遍历二叉树:"; p_BiSearchTree->VisitBiTreePreOrder(PrintNode); cout<<endl<<"中序遍历二叉树:"; p_BiSearchTree->VisitBiTreeInOrder(PrintNode); cout<<endl; while (0) { int k; cin.clear(); cin.sync(); cout<<"请输入要查找的节点值:"; cin>>k; cout<<p_BiSearchTree->Search(k)->k_data<<endl; } int i = 4; while (i) { int k; cin.clear(); cin.sync(); cout<<"请输入要删除的节点值:"; cin>>k; p_BiSearchTree->Delete(k); cout<<"前序遍历二叉树:"; p_BiSearchTree->VisitBiTreePreOrder(PrintNode); cout<<endl<<"中序遍历二叉树:"; p_BiSearchTree->VisitBiTreeInOrder(PrintNode); cout<<endl; i--; } delete p_BiSearchTree; system("pause"); return 0; }