二叉搜索树基本数据结构实现
2016-03-04 14:49
369 查看
二叉搜索树中一个结点包含3个指针left,right, prev和一个卫星数据key。这三个指针分别指向左儿子,右儿子,父节点。如果孩子结点和父亲结点不存在,相应指针为空。根结点的prev指向空。
1)遍历(中序遍历,先序遍历,后续遍历)
2)查找一个关键字,返回该关键字的结点指针
3).返回最大关键字最小关键字结点指针
4)寻找关键字key的后继结点
5)插入关键字key
6)构建一颗二叉搜索树
7)删除关键字key
1.遍历之中序遍历:递归中序遍历比较简单不多哆嗦。中序遍历非递归方法:首先需要一个栈来保存待遍历的结点:
a.先将根结点T=root压入栈S中
b.若结点T不空或者栈不空,将结点T沿途的左儿子全部压入栈中
c.栈顶元素T=S.top()出栈并访问之,如果T的右儿子存在,则将T右儿子进栈,然后T=T->right
d.重复步骤b
2.查找一个关键字key的方法:首先从树根开始比较。若key==x.key则找到,若key>x.key,则含关键字key的结点在x的右子树中,否则在左字树中。未找到则返回NULL。
3.返回最大最小元素:根据二叉搜索树性质可知,最大元素一定在树的最右端(该结点没有右儿子),最小结点一定在树的最左端(该结点没有左儿子)。
4.寻找关键字key的后继结点。 后继结点:一个结点x的后是大于x->key的最小关键字的结点。方法:如果结点x的右子树非空,x的后继一定是x右子树中最左的结点(右子树中key值最小结点),若x的右儿子不存在。则x的后继就要向上找,设y是向上寻找中移动的结点,直到遇到y是y父节点的左儿子为止,此时的y的父节点就是x的后继。
5.插入关键字key,先找到插入的位置(一定是某个叶节点处),然后修改指针插入。下面是递归函数代码(后面有非递归代码)
7.删除相对来说有点麻烦;分为四种情况,要删除的结点无儿子,只有左儿子,只有右儿子,同时有左右儿子。递归代码如下:
1)遍历(中序遍历,先序遍历,后续遍历)
2)查找一个关键字,返回该关键字的结点指针
3).返回最大关键字最小关键字结点指针
4)寻找关键字key的后继结点
5)插入关键字key
6)构建一颗二叉搜索树
7)删除关键字key
1.遍历之中序遍历:递归中序遍历比较简单不多哆嗦。中序遍历非递归方法:首先需要一个栈来保存待遍历的结点:
a.先将根结点T=root压入栈S中
b.若结点T不空或者栈不空,将结点T沿途的左儿子全部压入栈中
c.栈顶元素T=S.top()出栈并访问之,如果T的右儿子存在,则将T右儿子进栈,然后T=T->right
d.重复步骤b
2.查找一个关键字key的方法:首先从树根开始比较。若key==x.key则找到,若key>x.key,则含关键字key的结点在x的右子树中,否则在左字树中。未找到则返回NULL。
3.返回最大最小元素:根据二叉搜索树性质可知,最大元素一定在树的最右端(该结点没有右儿子),最小结点一定在树的最左端(该结点没有左儿子)。
4.寻找关键字key的后继结点。 后继结点:一个结点x的后是大于x->key的最小关键字的结点。方法:如果结点x的右子树非空,x的后继一定是x右子树中最左的结点(右子树中key值最小结点),若x的右儿子不存在。则x的后继就要向上找,设y是向上寻找中移动的结点,直到遇到y是y父节点的左儿子为止,此时的y的父节点就是x的后继。
5.插入关键字key,先找到插入的位置(一定是某个叶节点处),然后修改指针插入。下面是递归函数代码(后面有非递归代码)
<span style="font-size:12px;">BST* Insert(BST *BT, int key){ /*此代码中没有prev指针*/ if (!BT){ //找到啦要插入的位置 BT = new Tree; /*生成结点*/ BT->key = key;//插入 BT->left = BT->right = NULL; } else if (key > BT->key) BT->right = Insert(BT->right, key); //递归插入到左子树 else if (key < BT->key) BT->left = Insert(BT->left,key); //插入到右子树 return BT; //有相等的数就不用插入了 }</span>6.构建二叉搜索树就是不断地插入关键字
7.删除相对来说有点麻烦;分为四种情况,要删除的结点无儿子,只有左儿子,只有右儿子,同时有左右儿子。递归代码如下:
<span style="font-size:12px;">template<typename T> Node<T>* Delete(Node<T>*Root, T key){ Node<T>*x = nullptr; if (!Root) return nullptr; //空指针无法删除 if (key > Root->key){ //右子树中删除 x = Delete(Root->right, key); Root->right = x; if (x) //有可能x为空,要注意 x->prev = Root; } else if (key < Root->key){ //左子树中删除 x = Delete(Root->left, key); Root->left = x; if (x) //有可能x为空,要注意 x->prev = Root; } else{ //找到了要删除的结点 x = Root; if (!Root->left&&!Root->right) //没有儿子 Root = nullptr; else if (!Root->left){ //只有右儿子 Root = Root->right; if (!x->prev) //x是根结点 Root->prev = nullptr; else if (x->prev->right == x) //x是右儿子 x->prev->right = Root; else //x是左儿子 x->prev->left = Root; Root->prev = x->prev; delete x; } else if (!Root->right){ //只有左儿子 Root = Root->left; if (!x->prev) //x是根结点 Root->prev = nullptr; else if (x->prev->right == x) //x是右儿子 x->prev->right = Root; else //x是左儿子 x->prev->left = Root; Root->prev = x->prev; delete x; } else{ //两个儿子都有 x = x->right; while (x->left) x = x->left; //向左找到替换的结点 Root->key = x->key; //卫星数据覆盖 Node<T>*y = Delete(Root->right, x->key); //在Root右子树删除x->key if (y) //漏掉可能异常 y->prev = Root; Root->right = y; } } return Root; } </span>以下是二叉搜索树基本数据结构非递归的C++实现。注意模板类的定义和实现在都包含在头文件中。
/*bintree.head*/ #pragma once #include<iostream> #include<stack> using namespace std; template<typename T> struct Node{ T key; Node<T>*left = nullptr, *right = nullptr, *prev = nullptr; }; template<typename T> class BinTree{ private: Node<T>* root; int totalNode_; void Transplant(Node<T>*u,Node<T>*v); public: BinTree<T>(){ root = nullptr; totalNode_ = 0; } Node<T>*getRoot()const{ return root; } int getNumberOfNode()const{ return totalNode_; } void insertKey(T const &key); void creatBinTree(T const *a, int const &n); void inorderPrint(); Node<T>* findKey(T const &key); bool deleteKey(T const &key); Node<T>* treeMaxMum(); Node<T>* treeMinMum(); Node<T>* treeSuccessor(Node<T>*z); }; template <typename T> void BinTree<T>::insertKey(T const &key){ Node<T>* y = new Node<T>; //申请空间 y->key = key; y->left = y->right = y->prev = NULL; //初始化指针 if (!root){ //插入到头结点 root = y; return; } Node<T>* x = root; Node<T>* X_Prev = nullptr; //表示x的前驱 while (x != nullptr){ X_Prev = x; if (key > x->key) x = x->right; else x = x->left; } //将y插入在X_Prev后面 y->prev = X_Prev; if (key > X_Prev->key) X_Prev->right = y; else X_Prev->left = y; totalNode_++; } template<typename T> void BinTree<T>::inorderPrint(){ stack<Node<T>*> S; Node<T>*nowNode = root; while (nowNode || !S.empty()){ while (nowNode){ //沿途左儿子全部压入栈 S.push(nowNode); nowNode = nowNode->left; } if (!S.empty()){ nowNode = S.top(); S.pop(); //顶元素出栈 cout << nowNode->key << " "; nowNode = nowNode->right; //转向右儿子 } } cout << endl; } template <typename T> void BinTree<T>::creatBinTree(T const *a, int const &n){ int i; for (i = 0; i < n; i++) insertKey(a[i]); } template <typename T> Node<T>* BinTree<T>::findKey(T const &key){ Node<T>*x = root; while (x){ if (key>x->key) //比当前节点大,则一定在当前节点右子树 x = x->right; else if (key < x->key) //小则在左子树 x = x->left; else break; //相等时即为找到 } return x; //找到就返回此节点,否则返回空 } template<typename T> Node<T>* BinTree<T>::treeMaxMum(){ Node<T>*x = root; while (x->right != nullptr){ x = x->right; } return x; } template<typename T> Node<T>* BinTree<T>::treeMinMum(){ Node<T>* x = root; while (x->left != nullptr){ x = x->left; } return x; } template<typename T> Node<T>* BinTree<T>::treeSuccessor(Node<T>* z){ Node<T>*x = z; if (x->right) { //如果有右子树,则一定是右子树的最小结点 x = x->right; while (x->left) x = x->left; return x; } /*否则一定在x的有左孩子的最低层祖先*/ Node<T>*y = x->prev; while (y&&x != y->left){ //向上寻找 x = y; y = x->prev; } return y; } template<typename T> void BinTree<T>::Transplant(Node<T>*u, Node<T>*v){//用使用根结点为v的子树替代根结点为u的子树 if (!u->prev) //u是总的树根 root = v; else if (u->prev->right == u) //u是右儿子 u->prev->right = v; else //u是左儿子 u->prev->left = v; if (v != nullptr) //空间点单独处理 v->prev = u->prev; } template<typename T> bool BinTree<T>::deleteKey(T const &key){ Node<T>*DeleteNode = findKey(key); if (!DeleteNode) return false; if (!DeleteNode->left) //如果没有左儿子或者没有儿子 Transplant(DeleteNode, DeleteNode->right); //直接用右子树代替 else if (!DeleteNode->right) //如果没有右儿子 Transplant(DeleteNode, DeleteNode->left); //直接用左子树代替 else{ //同时有左儿子和右儿子 Node<T>*y = DeleteNode->right; //寻找右边关键字最小的结点 while (y->left) y = y->left; //沿路向左找到来替换的儿子结点y if (y != DeleteNode->right){ //如若顶替的结点不是要删除结点的右儿子 Transplant(y, y->right); y->right = DeleteNode->right; DeleteNode->right->prev = y; /*这部分if语句是将结点y变为待替换子树结点的根*/ } Transplant(DeleteNode, y); //完成右边子树代替 y->left = DeleteNode->left; //处理DeleteNode左边子树 DeleteNode->left->prev = y; } return true; }</span>
/*源.cpp*/ #include"binTree.h" int main(){ /*测试*/ char a[8] = { 'i','d','y','b', 's','h','c','f'}; BinTree<char>NewTree; NewTree.creatBinTree(a,8); //构建二叉搜索树 NewTree.inorderPrint(); Node<char>*pos = NewTree.findKey('h'); cout << pos->key << endl; pos = NewTree.treeMinMum(); cout << pos->key << endl; pos = NewTree.findKey('c'); pos = NewTree.treeSuccessor(pos); cout << pos->key << endl; NewTree.insertKey('a'); NewTree.inorderPrint(); NewTree.deleteKey('b'); NewTree.inorderPrint(); return 0; }
相关文章推荐
- 数据结构之“Ordered List and Sorted List”(一)
- 数据结构——顺序栈的学习
- 2015年大二上-数据结构-查找-1-(4)-二叉树排序树中查找的路径
- 常用的数据结构及其算法
- 数据结构
- 网易云数据结构- Maximum Subsequence Sum
- 网易云数据结构-最大子列和问题
- 数据结构基础
- 数据结构基本八大排序算法
- Redis各种数据结构内存占用测试
- 2015年大二上-数据结构-查找-1-(3)-二叉排序树
- 数据结构(17)--图的遍历DFS和BFS
- 数据结构学习之队列
- 6-5-树的双亲表示法-树和二叉树-第6章-《数据结构》课本源码-严蔚敏吴伟民版
- SPL的常用数据结构(2)
- 数据结构(1):顺序表
- 数据结构——线性表
- c语言实现求最短路径(迪杰斯特拉算法,《数据结构》算法7.15)
- 2015年大二上-数据结构-查找-1-(2)-分块查找
- 2015年大二上-数据结构-查找-1-(1)-线性表的折半查找