详细相关性质 可查看维基百科"二叉查找树"
关键性质:1 设root为二叉查找树的结点
如果a是root的任意左结点 key[a] < key[root]
如果a是root的任意右结点 key[root] < key[a]
2 没有关键值相等的节点,中序遍历二叉查找树可得到一个关键字的有序序列
下述实现基于上面的图(丑了点,但不影响阅读,有向且父节点与子节点关系清晰)
#include <iostream> #include <crtdbg.h> using namespace std; /*二叉查找树*/ /*实现中假设关键元素互不相同*/ typedef int DataType; struct TreeNode { TreeNode() { right = NULL; left = NULL; } DataType data; TreeNode *right; TreeNode *left; }; struct BiTree { TreeNode *root; BiTree() { root=NULL; } ~BiTree() { Destroy(root); root = NULL; } void Destroy(TreeNode *p) { if (p == NULL) return; Destroy(p->left); Destroy(p->right); delete p; } /*先确定父结点位置,在确定子节点位置*/ bool Insert(const DataType &data) { TreeNode *pNew = new TreeNode; pNew->data = data; pNew->left = NULL; pNew->right = NULL; //TreeNode **p = &root;(可通过二级指针简化代码,但可读性较差) //while( (*p) != NULL) //{ // if (data == (*p)->data ) // return false; // else if (data < (*p)->data) // p = &( (*p)->left); // else // p = &( (*p)->right); //} //*p = pNew; //return true; TreeNode *p = root; TreeNode *temp = NULL; while(p != NULL) { temp = p; if (data == p->data ) return false; else if (data < p->data) p = p->left; else p = p->right; } if (temp == NULL) root = pNew; else (data < temp->data) ? (temp->left = pNew) : (temp->right = pNew); return true; } //寻找关键字为data的节点,若找到删除返回true,否则返回false bool Delete(const DataType &data) { TreeNode *p = root; while(p != NULL) { if (data == p->data ) { Delete(p); return true; } else if (data < p->data) p = p->left; else p = p->right; } return false; } /*考虑3种情况,要删除的结点有两子节点,只有一个子节点,没有子节点*/ void Delete(TreeNode *p) { TreeNode *temp; TreeNode *parent = NULL; if (p->left == NULL && p->right == NULL)//左右子树都空 { parent = GetParent(root, p); (parent->left->data == p->data)? (parent->left = NULL) : (parent->right = NULL); delete p; p = NULL; } else if (p->right == NULL)//右子树为空 { temp = p->left; p->data = p->left->data; p->left = temp->left; p->right = temp->right; delete temp; temp = NULL; } else if (p->left == NULL)//左子树为空 { temp = p->right; p->data = p->right->data; p->left = temp->left; p->right = temp->right; delete temp; temp = NULL; } else//左右子树都不为空 { temp = TreePre(p);//寻找p的前驱,进行替换,然后删除前驱节点 if (temp != NULL) { p->data = temp->data; parent = GetParent(root, temp); (parent->left->data == temp->data)? (parent->left = NULL) : (parent->right = NULL); delete temp; temp = NULL; } } } /*非线性结构转换成线性结构(内存是线性的) 有3种方法 先序 中序 后序*/ /*中序遍历*/ void InOrderTree(TreeNode *p) { if (p == NULL) return ; InOrderTree(p->left); cout << p->data << endl; InOrderTree(p->right); } /*递归版本*/ TreeNode* Search(TreeNode *p, DataType key) { if (p == NULL || p->data == key) return p; if (key < p->data) { return Search(p->left, key); } else { return Search(p->right, key); } } /*非递归版本*/ TreeNode* Find(DataType key) { TreeNode *p = root; while(p != NULL && p->data != key) { if (key < p->data) { p = p->left; } else { p = p->right; } } return p; } /*寻找最小值*/ TreeNode* Minimum(TreeNode *p) { TreeNode *pTemp = p; while(pTemp != NULL) { p = pTemp; pTemp = p->left; } return p; } /*寻找最大值*/ TreeNode* Maximum(TreeNode *p) { TreeNode *pTemp = p; while(pTemp != NULL) { p = pTemp; pTemp = p->right; } return p; } /*获取父节点*/ /*此处为递归,也可以是尾递归,利用栈作为辅助的数据结构,具体实现可查看 普通树的第7点*/ TreeNode * GetParent(TreeNode *parent, TreeNode *p) { if (parent == NULL || parent == p) return NULL; if (parent->left == p || parent->right == p) { return parent; } TreeNode *ret = GetParent(parent->left, p); if(ret) return ret; return GetParent(parent->right, p); } /*寻找前趋(关键字都不相同) x的前趋为小于key[x]的 最大关键值 考虑两种情况 1 如果结点x的左子树非空,则x的前趋为左子树中的最右结点 2 如果结点x的左子树为空,则x的前趋为x的祖先结点,且x的只能为其父结点的右子结点 */ TreeNode *TreePre(TreeNode *p) { if (p->left) { return Maximum(p->left); } TreeNode *parent = GetParent(root,p); while(parent != NULL && p == parent->left) { p = parent; parent = GetParent(root,parent); } return parent; } /*寻找后继(关键字都不相同) x的后继为大于key[x]的 最小关键值 考虑两种情况 1 如果结点x的右子树非空,则x的后继为右子树中的最左结点 2 如果结点x的右子树为空,则x的后继为x的祖先结点,且x的只能为其父结点的左子结点 */ TreeNode *TreeAfter(TreeNode *p) { if (p->right) { return Minimum(p->right); } TreeNode *parent = GetParent(root,p); while(parent != NULL && p == parent->right) { p = parent; parent = GetParent(root,parent); } return parent; } }; void main() { _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); BiTree biTree; /*测试插入*/ biTree.Insert(15); biTree.Insert(6); biTree.Insert(3); biTree.Insert(7); biTree.Insert(2); biTree.Insert(4); biTree.Insert(13); biTree.Insert(9); biTree.Insert(18); biTree.Insert(17); biTree.Insert(20); biTree.InOrderTree(biTree.root); /*测试最大最小*/ cout << endl; TreeNode * p = NULL; p = biTree.Maximum(biTree.root); cout << p->data << endl; p = biTree.Minimum(biTree.root); cout << p->data << endl; /*测试两种find 以及获取父节点GetParent*/ cout <<endl; TreeNode *p2 = NULL; p = biTree.Find(17); if (p != NULL) { p2 = biTree.GetParent(biTree.root, p); cout << p2->data << endl; } p = biTree.Search(biTree.root, 20); if (p != NULL) { cout << biTree.GetParent(biTree.root, p)->data << endl; } /*测试 9前趋、 13后继*/ cout <<endl; TreeNode *p3 = NULL; p3 = biTree.TreePre(biTree.Find(9)); if ( p3 != NULL) { cout << p3->data << endl; } p3 = biTree.TreeAfter(biTree.Find(13)); if ( p3 != NULL) { cout << p3->data << endl; } ///*测试 删除 3中情况*/ //cout <<endl; biTree.Delete(6); /*有两结点*/ //biTree.Delete(13); /*只有一个子节点*/ //biTree.Delete(20); /*没有子节点*/ biTree.InOrderTree(biTree.root); system("pause"); }
@2015, 4-18 优化Insert/Delete函数实现 添加关键性质