二叉排序树
2016-03-04 20:38
423 查看
一:概念介绍
二叉排序树又称“二叉查找树”、“二叉搜索树”。
二叉排序树:或者是一棵空树,或者是具有下列性质的二叉树:
1. 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
2. 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
3. 它的左、右子树也分别为二叉排序树。
例如下图就是一个二叉排序树:
二:代码main部分
经过12次的数据插入(包括2次重复插入)所构成的排序树为:
经过两次删除所得的输出结果为:
三:函数具体解析
1.初始构造函数
2.查找操作:
在根节点_root所指的二叉排序树递归的查找其关键字等于key的数据元素,若查找成功,则指针result指向该元素节点,并返回true;否则指针result指向查找路径上访问的最后一个节点并返回false。指针parent指向result的父母,其中result和parent是定义在类的public成员。
这里要解释一下flag的作用,它是用来标记是否将result和parent恢复初始状态(也就是nullptr)。为什么要恢复呢?因为一个类对象第二次调用查找函数时,它的result和parent还保留着上一次的结果。你可能想到,那也可以不必设置flag啊,直接在每次调用时直接赋值为nullptr不就行了?你忽略了一个事实,该函数是递归函数,每次递归都会恢复初始值。
3.数据插入:
当二叉排序树不存在关键字等于key的数据元素时,插入key并返回true。
4.删除操作:
若二叉排序树中存在关键字等于key的数据元素,删除该元素节点
5.层次遍历:
二叉排序树又称“二叉查找树”、“二叉搜索树”。
二叉排序树:或者是一棵空树,或者是具有下列性质的二叉树:
1. 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
2. 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
3. 它的左、右子树也分别为二叉排序树。
例如下图就是一个二叉排序树:
二:代码main部分
#include<iostream> #include<queue> using namespace std; struct Node { int data; Node* lChild; Node* rChild; Node() { lChild = rChild = nullptr; data = 0; } }; class BSTree { public: Node* root;//根节点 Node* parent; Node* result; bool flag; BSTree(); bool SearchBST(Node* _root, int key); //查找 bool InsertBST(Node* _root, int key); //插入 bool Delete(Node* node); bool DeleteBST(Node* _root, int key); //删除 void LevelOrder(Node* _root); //层次遍历 }; int main() { BSTree tree; tree.InsertBST(tree.root, 45); tree.InsertBST(tree.root, 12); tree.InsertBST(tree.root, 53); tree.InsertBST(tree.root, 3); tree.InsertBST(tree.root, 3); tree.InsertBST(tree.root, 37); tree.InsertBST(tree.root, 100); tree.InsertBST(tree.root, 24); tree.InsertBST(tree.root, 61); tree.InsertBST(tree.root, 90); tree.InsertBST(tree.root, 90); tree.InsertBST(tree.root, 78); tree.LevelOrder(tree.root);//层次遍历 tree.DeleteBST(tree.root, 45); tree.DeleteBST(tree.root, 61); tree.LevelOrder(tree.root);//层次遍历 return 0; }
经过12次的数据插入(包括2次重复插入)所构成的排序树为:
经过两次删除所得的输出结果为:
三:函数具体解析
1.初始构造函数
BSTree::BSTree() { root = parent = result = nullptr; flag = true; }
2.查找操作:
bool BSTree::SearchBST(Node* _root, int key) { if(flag) parent = result = nullptr; if (!_root) //查找不成功 { flag = true; result = parent; return false; } else if (key == _root->data) //查找成功 { flag = true; result = _root; return true; } else if (key < _root->data) //左子树查找 { flag = false; parent = _root; return SearchBST(_root->lChild, key); } else //右子树查找 { flag = false; parent = _root; return SearchBST(_root->rChild, key); } }
在根节点_root所指的二叉排序树递归的查找其关键字等于key的数据元素,若查找成功,则指针result指向该元素节点,并返回true;否则指针result指向查找路径上访问的最后一个节点并返回false。指针parent指向result的父母,其中result和parent是定义在类的public成员。
这里要解释一下flag的作用,它是用来标记是否将result和parent恢复初始状态(也就是nullptr)。为什么要恢复呢?因为一个类对象第二次调用查找函数时,它的result和parent还保留着上一次的结果。你可能想到,那也可以不必设置flag啊,直接在每次调用时直接赋值为nullptr不就行了?你忽略了一个事实,该函数是递归函数,每次递归都会恢复初始值。
3.数据插入:
当二叉排序树不存在关键字等于key的数据元素时,插入key并返回true。
bool BSTree::InsertBST(Node* _root, int key) { if (!SearchBST(_root, key)) { Node* p = new Node; p->data = key; if (!result)//如果是空树 root = p; else if (key < result->data) result->lChild = p; else result->rChild = p; return true; } return false; }
4.删除操作:
若二叉排序树中存在关键字等于key的数据元素,删除该元素节点
bool BSTree::Delete(Node* node) { if (!node->rChild)//右子树空 { (node->data > parent->data) ? parent->rChild : parent->lChild = node->lChild; delete node; } else if (!node->lChild)//左子树空 { (node->data > parent->data) ? parent->rChild : parent->lChild = node->rChild; delete node; } else//左右子树都不空 { Node* q = node; Node* s = node->lChild; while (s->rChild) { q = s; s = s->rChild; } node->data = s->data; if (q != node) q->rChild = s->lChild; else q->lChild = s->lChild; delete s; } return true; } bool BSTree::DeleteBST(Node* _root, int key) { if (!_root || !SearchBST(_root, key))//空树或不存在key return false; else return Delete(result); }
5.层次遍历:
void BSTree::LevelOrder(Node* _root) { queue<Node*> q; if (!_root) return;//空树直接退出 q.push(_root); while (!q.empty()) { Node* p = q.front(); q.pop(); cout << p->data << " "; if (p->lChild) q.push(p->lChild); if (p->rChild) q.push(p->rChild); } cout << endl << endl; }
相关文章推荐
- 算法拾遗
- 关于adaboost的一些浅见
- JavaScript第五天
- 网站资源批量下载
- poj1011——剪枝dfs搜索题
- iOS开发---判断字符串为汉字或字母,并计算其数字个数
- 大数问题
- 蓝桥杯(大臣的旅费)
- Java 多线程(三)——线程的生命周期
- HttpClient4.5教程-序言
- window下彻底卸载删除SQL Serever 2012
- 化学
- HTML和CSS <h1> --3-- <h1>
- OC_属性点语法
- SDI运行出现“建立空文档失败”的解决方法
- 【转】sublimegit gitosc 私有项目每次输入密码
- iOS POST笔记
- 杭电2058
- 返回引用和对象
- 浅谈C++变量(对象)初始化问题