二叉树的面试题

来源:互联网 发布:淘宝运营提成比例 编辑:程序博客网 时间:2024/05/16 14:36

二叉树的面试题


1.递归创建二叉树;
2.由前序遍历和中序遍历重建二叉树(前序序列:1 2 3 4 5 6 - 中序序列:3 2 4 1 6 5);
3.前、中、后三种遍历的递归;
4.层次遍历-队列应用;
5.前、中、后三种遍历的非递归-用桟实现非递归;
6.求结点的个数;
7.求二叉树的高度;
8.求叶子结点的个数;
9.查找一个数据;
10.求第k层结点的个数;
11.求二叉树的镜像;
12.判断二叉树是不是完全二叉树;

<span style="font-size:18px;">#pragma once#include<iostream>using namespace std;#include<assert.h>#include<queue>#include<stack>template <class T>struct BinaryTreeNode{BinaryTreeNode<T>* _left;BinaryTreeNode<T>* _right;T _data;BinaryTreeNode(T data):_left(NULL), _right(NULL), _data(data){}};template <class T>class BinaryTree{typedef BinaryTreeNode<T> Node;public:BinaryTree():_root(NULL){}/////////////////////////////递归创建二叉树//////////////////////////////BinaryTree(const T* arr, int len, const T& invalid){assert(arr);int index = 0;_CreateBinaryTree(_root, arr, len, index, invalid);}//由前序遍历和中序遍历重建二叉树(前序序列:1 2 3 4 5 6 - 中序序列:3 2 4 1 6 5)BinaryTree(T* Prev,T* InOrder,int len){assert(Prev);assert(InOrder);_ReBuildCreateBinaryTree(_root,Prev,InOrder,len);}//前、中、后三种遍历的递归void PreOrder(){_PreOrder(_root);cout << endl;}void InOrder(){_InOrder(_root);cout << endl;}void PostOrder(){_PostOrder(_root);cout << endl;}/////////////////////////层次遍历-队列应用/////////////////////////////////void LevelTraverse(){queue<Node*> q;if (_root)q.push(_root);while (!q.empty()){Node* front = q.front();cout << front->_data << " ";q.pop();if (front->_left)q.push(front->_left);if (front->_right)q.push(front->_right);}cout << endl;}//前、中、后三种遍历的非递归-用桟实现非递归//前序非递归:访问当前结点,利用栈的特性后进先出,将右结点先//入桟,再将左结点入桟,这样先访问左,再访问右void PreOrder_Non(){stack<Node*> s;if (_root)s.push(_root);while (!s.empty()){Node* top = s.top();cout << top->_data << " ";s.pop();if (top->_right)s.push(top->_right);if (top->_left)s.push(top->_left);}cout << endl;}//////////////中序遍历:先将左子树入桟,再访问,再将右子树入桟/////////////////////void InOrder_Non(){stack<Node*> s;Node* cur = _root;while (cur || !s.empty()){while (cur){s.push(cur);cur = cur->_left;}cur = s.top();s.pop();cout << cur->_data << " ";cur = cur->_right;}cout << endl;}//////////////////////////////////后续遍历,prev法/////////////////////////////void PostOrder_Non(){stack<Node*> s;Node* cur = _root;Node* prev = NULL;while (cur || !s.empty()){//左子树入桟while (cur){s.push(cur);cur = cur->_left;}cur = s.top();//prev指向前一个被访问过的结点,右子树入桟if (cur->_right && prev != cur->_right){cur = cur->_right;}//当右子树为空且该结点没有被访问过,则去访问该结点else{cout << cur->_data << " ";prev = cur;s.pop();cur = NULL;}}cout << endl;}///////////////////////////////后续遍历,双桟法////////////////////////////void PostOrder_Non_Two_Stack(){if (_root == NULL)return;stack<Node*> s1, s2;s1.push(_root);while (!s1.empty()){Node* top = s1.top();s1.pop();s2.push(top);if (top->_left)s1.push(top->_left);if (top->_right)s1.push(top->_right);}while (!s2.empty()){Node* top = s2.top();cout << top->_data << " ";s2.pop();}cout << endl;}////////////////////////////求结点的个数///////////////////////////////////递归size_t Size(){size_t _size = _Size(_root);return _size;}//////////////加在一个静态变量上引入多线程安全问题///////////////////////size_t Size1(){size_t _size1 = _Size1(_root);return _size1;}///////////////////////引用解决了多线程安全问题/////////////////////////size_t Size2(){int index = 0;size_t _size2 = _Size2(_root, index);return _size2;}///////////////////////////求二叉树的高度/////////////////////////////size_t Height(){size_t height = _Height(_root);return height;}///////////////////////////求叶子结点的个数//////////////////////////size_t LeafNum(){size_t leaf = _LeafNum(_root);return leaf;}///////////////////////////查找一个数据///////////////////////////bool Find(const T& x){return _Find(_root, x);}////////////////////////求第k层结点的个数////////////////////////size_t KLayerOfNodeNum(int k){size_t num = 0;num = _KLayerOfNodeNum(_root,k);return num;}///////////////////////求二叉树的镜像////////////////////////////void GetMirror(){_root = _GetMirror(_root);}#include<queue>//////////////////判断二叉树是不是完全二叉树///////////////////////////////方法一:广度优先遍历二叉树////////////bool IsCompleteBinaryTree(){if (_root == NULL)return true;//bool isCompleteTree = false;bool HasLeftNoRight = false;queue<Node*> q;q.push(_root);while (!q.empty()){Node* front = q.front();q.pop();//第二次遇到只有左子树的结点if (front->_left && front->_right == NULL && HasLeftNoRight){return false;}if (front->_left && front->_right){//在遇到只有左子树的情况之后,必定不能往进去压结点if (HasLeftNoRight){return false;}q.push(front->_left);q.push(front->_right);}else if (front->_left && front->_right == NULL && !HasLeftNoRight){q.push(front->_left);//HasLeftNoRight为true时表示已经遇到只有左子树的情况HasLeftNoRight = true;}else if (front->_left == NULL && front->_right){return false;}else{//isCompleteTree = true;}} //return isCompleteTree;return true;}////////////方法二:按照完全二叉树的定义,左树的深度大于等于右树的深度////////////////////////一棵树一棵树的递归,前序遍历的过程//////////////bool IsCompleteBinaryTree2(){return _IsCompleteBinaryTree2(_root);}protected:void _CreateBinaryTree(Node*& root, const T* arr, int len, int& index, const T& invalid){if (root == NULL && index < len && arr[index] != invalid){root = new Node(arr[index]);_CreateBinaryTree(root->_left, arr, len, ++index, invalid);_CreateBinaryTree(root->_right, arr, len, ++index, invalid);}}void _ReBuildCreateBinaryTree(Node*& root, T* Prev, T* InOrder, \int len){if (Prev == NULL && InOrder == NULL && len <= 0)return;return _ReBuildTree(root, Prev, Prev + len - 1, InOrder, InOrder + len - 1);}void _ReBuildTree(Node*& root,T* StartPre,T* EndPre, \T* StartIn, T* EndIn){//1.前序确定根结点int rootValue = StartPre[0];root = new Node(rootValue);//2.(1).只有一个结点if (StartPre == EndPre){if (StartIn == EndIn && *StartPre == *StartIn){return;}else{cout << "Prev and InOrder is not Catching!" << endl;return;}}//2.(2).有多个结点,通过在中序中找到根结点T* rootIn = StartIn;while (rootIn < EndIn && *rootIn != root->_data){++rootIn;}if (rootIn == EndIn && *rootIn != root->_data){cout << "Prev and InOrder is not Catching!" << endl;return;}//3.上面找到根结点,同时通过此中序中的根结点计算出左子树结点的个数int NumOfLeft = rootIn - StartIn;//4.通过根的左子树的个数在前序中计算左子树最后一个数据的位置T* LastPlaceOfLeft = StartPre + NumOfLeft;//5.递归构建左子树if (NumOfLeft > 0){_ReBuildTree(root->_left, StartPre + 1, LastPlaceOfLeft, StartIn, rootIn - 1);}//6.递归构建右子树if (NumOfLeft < EndPre - StartPre){_ReBuildTree(root->_right, LastPlaceOfLeft + 1, EndPre, rootIn + 1, EndIn);}}void _PreOrder(Node* root){if (root == NULL)return;cout << root->_data << " ";_PreOrder(root->_left);_PreOrder(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;}size_t _Size1(Node* root){if (root == NULL)return 0;static int count = 0;++count;_Size1(root->_left);_Size1(root->_right);return count;}size_t _Size2(Node* root,int& count){if (root == NULL)return 0;++count;_Size2(root->_left, count);_Size2(root->_right, count);return count;}size_t _Height(Node* root){if (root == NULL)return 0;size_t left = _Height(root->_left);size_t right = _Height(root->_right);return left + 1 > right + 1 ? left + 1 : right + 1;}size_t _LeafNum(Node* root){if (root == NULL)return 0;if (root->_left == NULL && root->_right == NULL)return 1;size_t leftOfLeaf = _LeafNum(root->_left);size_t rightOfLeaf = _LeafNum(root->_right);return leftOfLeaf + rightOfLeaf;}bool _Find(Node*& root, const T& x){if (root && root->_data == x)return true;if (root->_left)return _Find(root->_left, x);if (root->_right)return _Find(root->_right, x);return false;}size_t _KLayerOfNodeNum(Node* root,const int& k){if (root == NULL || k < 1)return 0;if (k == 1)return 1;//k层结点=左子树的k - 1层的结点 + 右子树的k - 1层的结点size_t KOfLeft = _KLayerOfNodeNum(root->_left, k - 1);size_t ROfRight = _KLayerOfNodeNum(root->_right, k - 1);return KOfLeft + ROfRight;}Node* _GetMirror(Node* root){if (root == NULL)return NULL;//求左子树与右子树的镜像Node* leftMirror = _GetMirror(root->_left);Node* rightMirror = _GetMirror(root->_right);//交换左右子树 root->_left = rightMirror;root->_right = leftMirror;return root;}bool _IsCompleteBinaryTree2(Node* root){if (root == NULL)return true;int left = _Height(root->_left);int right = _Height(root->_right);if (left - right < 0 || left - right > 1){return false;}return _IsCompleteBinaryTree2(root->_left) && _IsCompleteBinaryTree2(root->_right);}private:Node* _root;};void TestBinaryTree(){//int a[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };//int a[15] = { 1, 2, '#', 3, '#', '#', 4, 5, '#', 6, '#', 7, '#', '#', 8 };//int a[] = { 1, 2, '#', 3, '#', '#', 4, 5, 6, '#', 7, 8 };int a[] = { 0, 1, 3, 7,'#', '#', 8, '#', '#', 4, 9, '#', '#','#', 2, 5, '#', '#', 6 };//int a[] = { 1, 2, '#', 4, '#', '#', 3};BinaryTree<int> bt(a, sizeof(a) / sizeof(a[0]),'#');//前、中、后三种遍历的递归测试及层次遍历测试bt.PreOrder();bt.InOrder();                            bt.PostOrder();bt.LevelTraverse();//前、中、后三种遍历的非递归测试bt.PreOrder_Non();bt.InOrder_Non();bt.PostOrder_Non();bt.PostOrder_Non_Two_Stack();//总结点个数、高度、叶子结点个数、k层结点个数、查找函数及二叉树镜像问题cout <<"Size():"<< bt.Size() << endl;cout <<"Size1():"<< bt.Size1() << endl;cout <<"Size2():"<< bt.Size2() << endl;cout <<"Height:"<< bt.Height() << endl;cout <<"LeafNum():"<< bt.LeafNum() << endl;cout <<"KLayerOfNodeNum(3):"<< bt.KLayerOfNodeNum(3) << endl;//bt.GetMirror();cout << "IsCompleteBinaryTree()?" << bt.IsCompleteBinaryTree() << endl;cout << "IsCompleteBinaryTree2()?" << bt.IsCompleteBinaryTree2() << endl;}void TestPrevAndInReBuildBinaryTree(){int PrevOrder[] = { 0, 1, 3, 7, 8, 4, 9, 2, 5, 6 };int InOrder[] = { 7, 3, 8, 1, 9, 4, 0, 5, 2, 6 };BinaryTree<int> bt(PrevOrder, InOrder, sizeof(PrevOrder) / sizeof(PrevOrder[0]));}</span>


1 0
原创粉丝点击