二叉树以及相关的面试题
来源:互联网 发布:java 安卓开发 编辑:程序博客网 时间:2024/05/21 13:35
为了研究二叉树我们的先了解一些树的基本概念:
树是n(n>=0)个有限个数据的元素集合,形状像一颗倒过来的树。
节点:结点包含数据和指向其它节点的指针。
根节点:树第一个结点称为根节点。
结点的度:结点拥有的子节点个数。
叶节点:没有子节点的节点(度为0)。
父子节点:一个节点father指向另一个节点child,则child为孩子节点,father为父亲节点。
兄弟节点:具有相同父节点的节点互为兄弟节点。
节点的祖先:从根节点开始到该节点所经的所有节点都可以称为该节点的祖先。
子孙:以某节点为根的子树中任一节点都称为该节点的子孙。
树的高度:树中距离根节点最远节点的路径长度。
二叉树: 二叉树是一棵特殊的树,二叉树每个节点最多有两个孩子结点,分别称为左孩子和右孩子。
满二叉树: 高度为N的满二叉树有2^N- 1个节点的二叉树。
完全二叉树: 若设二叉树的深度为h,除第h 层外,其它各层(1~h-1) 的结点数都达到最大个数,第h
层所有的结点都连续集中在最左边,这就是完全二叉树
实现一个树我们可以完成以下操作:
1. 树的前序遍历(递归以及非递归)
2. 树的中序遍历(递归以及非递归)
3. 树的后序遍历(递归以及非递归)
4. 层序遍历
4. 拷贝构造
5. 赋值运算符重载
面试爱考的:
1. 求树的所有节点个数
2. 树的叶节点个数
3. 树的第k层节点个数
4. 树的深度
5. 查找节点
为了实现一个树 ,我们的先构造它的节点
template<class T>struct BinaryTreeNode{ BinaryTreeNode<T>* _left; //左节点 BinaryTreeNode<T>* _right; //右节点 T _data; //存放数据 BinaryTreeNode(const T& x) //构造节点 :_data(x) , _left(NULL) , _right(NULL) {}};
有了节点我们需要构造出来一棵树
BinaryTree(T* a, size_t n, const T& invalid) //构造树 { size_t index = 0; _root = CreateTree(a, n, invalid, index); }Node* CreateTree(T*a, size_t n, const T& invalid, size_t& index) { Node* root = NULL; while (index < n&&a[index] != invalid) //invalid无效值 { root = new Node(a[index]); root->_left = CreateTree(a, n, invalid, ++index); //先构造左树 root->_right = CreateTree(a, n, invalid, ++index);//再构造右树 } return root; }
树的前序递归遍历
void PrevOrder() //前 { _PrevOrder(_root); cout << endl; }void _PrevOrder(Node* root) { if (root == NULL) { return; } cout << root->_data << " "; _PrevOrder(root->_left); _PrevOrder(root->_right); }
树的前序非递归遍历
void PrevOrderNor()// 前序非递归遍历 { Node* cur = _root; stack<Node*> s; //借助栈 while (cur != NULL || !s.empty()) { while (cur) { s.push(cur); cout << cur->_data<<" "; cur = cur->_left; } Node* top = s.top(); s.pop(); cur = top->_right; } cout << endl; }
树的中序遍历(递归以及非递归)还有树的后序遍历(递归)和
树的前序遍历类似我就不再解释
在这里我要说说树的后序遍历非递归
void PostOrderNor() //后序遍历非递归 { Node* cur = _root; Node* Next = NULL; stack<Node*> s; while (cur || !s.empty()) { while (cur) { s.push(cur); cur = cur->_left; } Node* top = s.top(); if (top->_right == NULL||top->_right==Next) { cout << top->_data << " "; Next = top; s.pop(); } else { cur = top->_right; } } }
前边我已经详细的介绍了几个,剩下的接口我就不再一个一个介绍了
代码里需要注意的我都已经标出:
#pragma oncetemplate<class T>struct BinaryTreeNode{ BinaryTreeNode<T>* _left; //左节点 BinaryTreeNode<T>* _right; //右节点 T _data; //存放数据 BinaryTreeNode(const T& x) //构造节点 :_data(x) , _left(NULL) , _right(NULL) {}};template<class T>struct BinaryTree{ typedef BinaryTreeNode<T> Node;public: BinaryTree() :_root(NULL) {} BinaryTree(T* a, size_t n, const T& invalid) //构造树 { size_t index = 0; _root = CreateTree(a, n, invalid, index); } BinaryTree(const BinaryTree<T>& t) { _root = _Copy(t._root); } BinaryTree<T>& operator=(const BinaryTree<T>& t) { if (_root != t._root) { Node* tmp = _Copy(t._root); Destroy(_root); _root = tmp; } return *this; } ~BinaryTree() { Destroy(_root); } void PrevOrder() //前 { _PrevOrder(_root); cout << endl; } void PrevOrderNor()// 前序非递归遍历 { Node* cur = _root; stack<Node*> s; //借助栈 while (cur != NULL || !s.empty()) { while (cur) { s.push(cur); cout << cur->_data<<" "; cur = cur->_left; } Node* top = s.top(); s.pop(); cur = top->_right; } cout << endl; } void InOrder() //中 { _InOrder(_root); cout << endl; } void InOrderNor() //中序遍历非递归 { Node* cur = _root; stack<Node*> s; while (cur || !s.empty()) { while (cur) { s.push(cur); cur = cur->_left; } Node* top = s.top(); cout << top->_data << " "; s.pop(); cur = top->_right; } } void PostOrder() //后 { _PostOrder(_root); cout << endl; } void PostOrderNor() //后序遍历非递归 { Node* cur = _root; Node* Next = NULL; stack<Node*> s; while (cur || !s.empty()) { while (cur) { s.push(cur); cur = cur->_left; } Node* top = s.top(); if (top->_right == NULL||top->_right==Next) { cout << top->_data << " "; Next = top; s.pop(); } else { cur = top->_right; } } } void LevelOrder() //层序遍历 { queue<Node*> q; if (_root) q.push(_root); while (!q.empty()) { Node* front = q.front(); cout << front->_data << " "; if (front->_left) q.push(front->_left); if (front->_right) q.push(front->_right); q.pop(); } cout << endl; } size_t Size() //树的全部节点 { return _Size(_root); } size_t Leafsize() //树叶节点 { return _Leafsize(_root); } size_t GetkLevel(size_t K) //第k层节点 { return _GetkLevel(_root,K); } size_t depeth() // 树的深度 { return _depeth(_root); } Node* Find(const T& x) { return _Find(_root,x); }protected: Node* CreateTree(T*a, size_t n, const T& invalid, size_t& index) { Node* root = NULL; while (index < n&&a[index] != invalid) { root = new Node(a[index]); root->_left = CreateTree(a, n, invalid, ++index); root->_right = CreateTree(a, n, invalid, ++index); } return root; } Node* _Copy(Node* root) { if (root == NULL) return NULL; Node* tmp = new Node(root->_data); tmp->_left = _Copy(root->_left); tmp->_right = _Copy(root->_right); return tmp; } void Destroy(Node* root) { if (root == NULL) return; Destroy(root->_left); Destroy(root->_right); delete root; } void _PrevOrder(Node* root) { if (root == NULL) { return; } cout << root->_data << " "; _PrevOrder(root->_left); _PrevOrder(root->_right); } void _InOrder(Node* root) { if (root == NULL) { return; } _InOrder(root->_left); cout << root->_data << " "; _InOrder(root->_right); } void _PostOrder(Node* root) { if (root == NULL) { return; } _PostOrder(root->_left); _PostOrder(root->_right); cout << root->_data << " "; } size_t _Size(Node* root) //树的全部节点 { if (root == NULL) { return 0; } return _Size(root->_left) + _Size(root->_right) + 1; //求树的全部节点相当于求它的左子树的全部节点和右子树的全部节点加1 } size_t _Leafsize(Node* root) { if (root==NULL) { return 0; } if (root->_left == NULL&&root->_right == NULL) { return 1; //当一个节点的左右子树都为空就返回1 } int numleft = _Leafsize(root->_left); int numright = _Leafsize(root->_right); return numleft + numright; //求这个树的叶子节点 相当于递归求它左子树和右子树的全部叶节点 } size_t _GetkLevel(Node* root,size_t k) { if (root == NULL || k < 1) { return 0; } if (k == 1) //当k为1层返回1 { return 1; } return _GetkLevel(root->_left, k - 1) + _GetkLevel(root->_right, k - 1); } size_t _depeth(Node* root) { if (root == NULL) { return 0; } int numleft = _depeth(root->_left); int numright = _depeth(root->_right); return numleft > numright ? (numleft + 1) : (numright + 1); //不要写成下面这个代码因为在求大小的时候递归 然后返回的时候又递归 开销大 // return _depeth(root->_left) > _depeth(root->_right)?(_depeth(root->_left) + 1) : (_depeth(root->_right) + 1); } Node* _Find(Node* root,const T& x) { if (root == NULL) { return NULL; } if (root->_data == x) return root; Node* ret = _Find(root->_left, x); if (ret) return ret; //这里需要注意的是如果在左子树里边找到了就不用继续在右子树里查找了 else return _Find(root->_right, x); }protected: Node* _root;};void TestBinaryTree(){ int array[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 }; BinaryTree<int> t1(array, sizeof(array) / sizeof(array[0]), '#');// t1.PrevOrder();// t1.PrevOrderNor();// t1.InOrder();// t1.InOrderNor(); t1.PostOrder(); t1.PostOrderNor();// t1.LevelOrder();// BinaryTree<int>t2;// t2 = t1;// t2.PrevOrder();// cout << t1.Leafsize() << endl;// cout << t1.GetkLevel(4) << endl;// cout << t1.depeth() << endl; //BinaryTreeNode<int>* ret = t1.Find(10); //if (ret == NULL) //{ // cout << "不存在这个数" << endl; //} //else //{ // cout << ret->_data << endl; //}}
- 二叉树以及相关的面试题
- 二叉树相关的面试题
- 二叉树的相关面试题
- 和二叉树相关的面试题
- 二叉树相关的面试题<一>
- 二叉树的相关面试题<二>
- 面试题(二叉树相关)
- 面试题(二叉树相关)
- 二叉树相关面试题
- 【面试题】二叉树相关
- 二叉树面试题(基础篇二叉树的相关面试题(基础篇)
- 面试题精选(83):二叉树相关的问题
- 二叉树相关面试题集锦
- 二叉树相关面试题及代码
- 面试题二叉树相关问题总结
- 二叉树相关面试题汇总
- 二叉树相关面试题总结
- 二叉树基本操作以及面试题
- 初识Arduino
- Android常公用函数收集
- Python+scrapy+mysql实现爬取磁力链接
- 图片上传的controller
- LeetCode: 461. Hamming Distance
- 二叉树以及相关的面试题
- Java 反射获取方法
- JAVA UUID 生成
- 动态代理
- 潜伏与启动-1-NETSH
- 直接运行java类来调用webservce接口时发生错误
- 求指定区间内与n互素的数的个数 容斥原理
- 消息中间件-activemq实战整合Spring之Topic模式(五)
- uboot中gd_t和bd_t数据结构简介