二叉树
2016-06-08 17:53
106 查看
一、简单介绍
1、以前的数据结构重点都死在结构,而现在的二叉搜索树重在应用
2、二叉搜索树的简单性质
(1)每一个节点的key值都是不同的
(2)所有的节点的左节点都小于当前节点,所有的右节点大于当前节点
(3)所有节点的左右子树都是二叉搜索树
3、二叉搜索树应用在查找上面,时间复杂度与二分查找相类似
注意哈希表也是用来查找的(key形式是用来过滤的,而KV形式是用来查找信息的)
4、STL也有搜索树(以前只是对vector和list比较了解)
(1)map 是KV形式,底层实现是使用红黑树(也是一种二叉搜索树,是针对二叉搜索树的性质被设计出来的)
二叉搜索树的缺陷:在插入顺序为[0,1,2,3,4,5,6,7,8,9]的顺序插入顺序的时候,查找效率是比较低的,所以有了平衡树。红黑树
(2)set 是value形式的,底层实现是红黑树
c++11应用还应用了一下的两种用来查找的容器
(3)unorder_map是key/ value形式的,底层实现是使用哈希表(无序的)
(4)unorder_set是key形式的,底层实现是使用哈希表
5、上述的数据结构的区别和联系
(1)查找的时间复杂度为:红黑树o(lgN)而哈希表为o(1)(红黑树1000000只需要查找20次)
(2)效率不同
(3)JAVA中 unorder哈希表都挂在一个链上的时候,就自动挂为红黑树
二、大体声明
1、KV节点的定义:
2、大体声明
三、具体实现
1、默认构造函数
2、增删查(非递归写法)
(1)增
(2)查
(3)删(最麻烦)
3、增删查(递归写法)
(1)增
主函数:
递归函数:
(2)查
主函数:
递归函数:
(3)删
主函数:
递归函数:
1、以前的数据结构重点都死在结构,而现在的二叉搜索树重在应用
2、二叉搜索树的简单性质
(1)每一个节点的key值都是不同的
(2)所有的节点的左节点都小于当前节点,所有的右节点大于当前节点
(3)所有节点的左右子树都是二叉搜索树
3、二叉搜索树应用在查找上面,时间复杂度与二分查找相类似
注意哈希表也是用来查找的(key形式是用来过滤的,而KV形式是用来查找信息的)
4、STL也有搜索树(以前只是对vector和list比较了解)
(1)map 是KV形式,底层实现是使用红黑树(也是一种二叉搜索树,是针对二叉搜索树的性质被设计出来的)
二叉搜索树的缺陷:在插入顺序为[0,1,2,3,4,5,6,7,8,9]的顺序插入顺序的时候,查找效率是比较低的,所以有了平衡树。红黑树
(2)set 是value形式的,底层实现是红黑树
c++11应用还应用了一下的两种用来查找的容器
(3)unorder_map是key/ value形式的,底层实现是使用哈希表(无序的)
(4)unorder_set是key形式的,底层实现是使用哈希表
5、上述的数据结构的区别和联系
(1)查找的时间复杂度为:红黑树o(lgN)而哈希表为o(1)(红黑树1000000只需要查找20次)
(2)效率不同
(3)JAVA中 unorder哈希表都挂在一个链上的时候,就自动挂为红黑树
二、大体声明
1、KV节点的定义:
template<class K,class V> struct BSTNode { BSTNode<K, V>* _left; BSTNode<K, V>* _right; K _key; V _value; public: BSTNode(const K& key, const V& value) :_left(NULL) , _right(NULL) , _key(key) , _value(value) {} };
2、大体声明
template<class K,class V> class BSTree { typedef BSTNode<K, V> Node; public: BSTree(); public://增删查改的非递归写法 bool Insert(const K& key, const V& value);//返回值设计成bool防冗余 bool Remove(const K& key); Node* Find(const K& key)//不能该key,改key后整体会乱 public: Node* Find_R(const K& key); bool Insert_R(const K& key, const V& value); bool Remove_R(const K& key); protected://增删查改的递归写法,Remove和Insert巧用引用 Node* _Find_R(Node* root, const K& key); bool _Insert_R(Node*& root, const K& key, const V& value); bool _Remove_R(Node*& root, const K& key); public: void Inorder_NonR();//方便测试 protected: Node* _root; }
三、具体实现
1、默认构造函数
<pre name="code" class="cpp">BSTree() :_root(NULL) {}
2、增删查(非递归写法)
(1)增
bool Insert(const K& key, const V& value)//返回值设计成bool防冗余 { if (_root == NULL) { _root = new Node(key, value); return true; } Node* cur = _root; Node* parent = NULL;//记录cur的上一个节点 while (cur) { if (cur->_key < key) { parent = cur; cur = cur->_right; } else if (cur->_key>key) { parent = cur; cur = cur->_left; } else { return false; } } if (parent->_key > key) { parent->_left = new Node(key, value); } else { parent->_right = new Node(key, value); } return true; }
(2)查
Node* Find(const K& key)//不能该key,改key后整体会乱 { Node* cur = _root; while (cur) { if (cur->_key > key) { cur = cur->_left; } else if (cur->_key < key) { cur = cur->_right; } else return cur; } return NULL; }
(3)删(最麻烦)
bool Remove(const K& key) { if (_root == NULL) return false; if (_root->_left == NULL&&_root->_right == NULL)//是叶子节点或者根节点 { if (_root->_key == key) { delete _root; _root = NULL; return true; } else { return false; } } Node* parent = NULL; Node* cur = _root; while (cur) { if (cur->_key < key) { parent = cur; cur = cur->_right; } else if (cur->_key>key) { parent = cur; cur = cur->_left; } else//相等的情况 { Node* del = cur; if (cur->_left == NULL)//节点这有左子树或者右子树 { if (parent == NULL) { _root = cur->_right; } else { if (parent->_left == cur) { parent->_left == cur->_right; } else { parent->_right = cur->_right; } } } else if (cur->_right == NULL) { if (parent == NULL) { _root = cur->_left; } else { if (parent->_left == cur) { parent->_left = cur->_left; } else { parent->_right = cur->_left; } } } else {//找到最左的节点,替换法删除 parent = cur; Node* firstLeft = cur->_right; while (firstLeft->_left != NULL) { parent = firstLeft; firstLeft = firstLeft->_left; } std::swap(cur->_key, firstLeft->_key); std::swap(cur->_value, cur->_value); del = firstLeft; if (parent->_left == firstLeft) { parent->_left = firstLeft->_right;//因为为右子树的最左节点,所以没有左节点 } else { parent->_right = firstLeft->_right; } } delete del; return true; } } return false; }
3、增删查(递归写法)
(1)增
主函数:
bool Insert_R(const K& key, const V& value) { return _Insert_R(_root, key, value); }
递归函数:
bool _Insert_R(Node*& root, const K& key, const V& value) { if (root == NULL) { root = new Node(key, value); return true; } if (root->_key > key) { return _Insert_R(root->_left, key, value); } else if (root->_key < key) { return _Insert_R(root->_right, key, value); } else { return false; } }
(2)查
主函数:
Node* Find_R(const K& key) { return _Find_R(_root, key); }
递归函数:
Node* _Find_R(Node* root, const K& key) { if (root == NULL) { return NULL; } if (root->_key == key) { return root; } if (root->_key > key) { return _Find_R(root->_left, key); } else { return _Find_R(root->_right, key); } return NULL; }
(3)删
主函数:
bool Remove_R(const K& key) { return _Remove_R(_root, key); }
递归函数:
bool _Remove_R(Node*& root, const K& key) { if (root == NULL) { return false; } if (root->_key > key)//有的时候条件判断的顺序要变通一下,突出重点,而不是一味的按顺序 { return _Remove_R(root->_left, key); } else if (root->_key < key) { return _Remove_R(root->_right, key); } else { Node* del = root; if (root->_left == NULL) { root = root->_right;//root指针,而root->_right是将指针的值赋值给他,所以后面delete del是没有什么问题的 } else if (root->_right == NULL) { root = root->_left; } else { Node* firstLeft = root->_right;//寻找右子树的最左的叶子节点,或者寻找左子树的最右的叶子节点 while (firstLeft->_left != NULL) { firstLeft = firstLeft->_left; } std::swap(root->_key, firstLeft->_key); std::swap(root->_value, firstLeft->_value); return _Remove_R(root->_right, key);//只能写这种写法,是因为firstLeft的有节点可能存在,不能简单的置为NULL } //del = firstLeft;这种也是不对的因为firstLeft这个时候可能是有右节点的 delete del; del = NULL;//delet和NULL搭配使用 return true; } return false; }
相关文章推荐
- 搜狗百度360市值齐跌:搜索引擎们陷入集体焦虑?
- 本人即将筹备败家日志,敬请期待!
- IE:使用搜索助手
- C++深度优先搜索的实现方法
- 基于文本的搜索
- php实现搜索一维数组元素并删除二维数组对应元素的方法
- 使用Sphinx对索引进行搜索
- asp 多关键词搜索的简单实现方法
- C#使用foreach语句搜索数组元素的方法
- WordPress中用于获取搜索表单的PHP函数使用解析
- JavaScript中数组的排序、乱序和搜索实现代码
- jquery ztree实现树的搜索功能
- 【经典源码收藏】jQuery实用代码片段(筛选,搜索,样式,清除默认值,多选等)
- C#编程实现Excel文档中搜索文本内容的方法及思路
- sqlserver中在指定数据库的所有表的所有列中搜索给定的值
- 可以用来搜索当前页面内容的js代码
- 全文搜索和替换
- javascript搜索自动提示功能的实现第1/3页
- iOS应用中UISearchDisplayController搜索效果的用法
- mysql 模糊搜索的方法介绍