面试题之二叉树篇

来源:互联网 发布:js array contains 编辑:程序博客网 时间:2024/04/28 01:34

    二叉树是面试中很重要的考点,类似中序非递归遍历、最低公共祖先、镜像、路径求值等问题屡见不鲜。 在这里总结常见的一些题目,并给出模板实现,希望能给求职的朋友一些帮助,也方便自己时时回顾。如有错误,请不吝指教!

1. 有序数组递归建立二叉树
2. 求叶子节点个数
3. 求二叉树深度
4. 求镜像
5. 分层打印,打印一行后换行
6. 判断二叉树是否平衡
8. 判断是否是满二叉树
9. 二叉搜索树的最低公共祖先
10. 普通二叉树的最低公共祖先
11. 判断是否是二叉搜索树
12. 求二叉树第K层节点个数(根节点为第一层)
13. 二叉树节点间的最大距离
14. 前序非递归遍历
15. 中序非递归遍历
16. 后序非递归遍历
17. 判断序列是否是二叉搜索树的后序遍历序列
18. 求路径和为给定值的所有路径
19. 判断一二叉树是否是另一二叉树子树
20. 根据前序中序遍历重建二叉树
21. 判断二叉树结构是否轴对称
22. 二叉树转换为双向链表
23. 判断两棵二叉树是否结构相同
24. 求二叉树宽度(节点个数最多的一层有多少个)

 节点定义:

template <typename T>struct BinNode{T data;    BinNode *left, *right;};

1. 有序数组递归建立二叉树

template <typename T>BinNode<T> *CreateTree(T a[],int begin, int end){if (begin > end)return NULL;int mid = (begin + end) >> 1;BinNode<T> *p = new BinNode<T>;p->data = a[mid];p->left = CreateTree(a,begin,mid-1);p->right = CreateTree(a,mid+1,end);return p;}

2.  求叶子节点个数

template <typename T>int GetLeavesCounts(BinNode<T> *r){if (NULL == r)return 0;if (NULL == r->left && NULL == r->right)return 1;return GetLeavesCounts(r->left) + GetLeavesCounts(r->right);}

3. 求二叉树深度

template <typename T>int GetDepth(BinNode<T> *r){if (r == NULL)return 0;int lh = GetDepth(r->left);int rh = GetDepth(r->right);return lh>=rh?lh+1:rh+1;}

4. 求二叉树镜像

递归法:

template <typename T>                 void Mirror_Recurse(BinNode<T> *r){if (NULL == r)return;BinNode<T> * temp = r->left;r->left = r->right;r->right = temp;Mirror_Recurse(r->left);Mirror_Recurse(r->right);}

非递归法

template <typename T>void Mirror_NonRecurse(BinNode<T> *r){if (NULL == r)return ;queue<BinNode<T>*> q;q.push(r);while(!q.empty()){BinNode<T> * p = q.front();q.pop();BinNode<T> * temp = p->left;p->left = p->right;p->right = temp;if(p->left != NULL)q.push(p->left);if(p->right != NULL)q.push(p->right);}}

5. 分层打印,打印一行后换行

template <typename T>void PrintNodeLevelByLevel(BinNode<T> *r){if (r==NULL)return;vector<BinNode<T>*> v;v.push_back(r);int cur = 0;int last = v.size();while(cur < v.size()){last = v.size();while( cur < last){cout << v[cur]->data << " ";if (v[cur]->left != NULL)v.push_back(v[cur]->left);if (v[cur]->right != NULL)v.push_back(v[cur]->right);++cur;}cout << endl;}}

6. 判断二叉树是否平衡

template <typename T>int IsBanlanceSubTree(BinNode<T> *r, int &depth){if (NULL == r){ depth = 0;return 1;}int ldepth, rdepth;if (IsBanlanceSubTree(r->left, ldepth) && IsBanlanceSubTree(r->right, rdepth)){int diff = ldepth - rdepth;if (diff >= -1 && diff <= 1){depth = ldepth>rdepth ? ldepth+1 : rdepth+1;return 1;}}return 0;}template <typename T>int IsBanlanceTree(BinNode<T> *r){int depth;return IsBanlanceSubTree(r, depth);}

7. 判断是否是完全二叉树

template <typename T>int IsCompleteTree(BinNode<T> *r){if (NULL == r)return 1;queue<BinNode<T> *> q;q.push(r);while (!q.empty()){BinNode<T> *temp = q.front();q.pop();if(NULL == temp){while(!q.empty()){if (q.front() == NULL)q.pop();elsereturn 0;}return 1;}q.push(temp->left);q.push(temp->right);}return 0;}

8. 判断是否是满二叉树

template <typename T>int IsFullSubTree(BinNode<T> *r, int &depth){if (NULL == r){depth = 0;return 1;}int ldepth = 0;int rdepth = 0;if (IsFullSubTree(r->left, ldepth) && IsFullSubTree(r->right, rdepth)){if (ldepth == rdepth){depth = ldepth +  1;return 1;}}return 0;}template <typename T>int IsFullTree(BinNode<T> *r){int depth = 0;returnIsFullSubTree(r, depth);}

9. 二叉搜索树的最低公共祖先

template <typename T>int FLCABST(BinNode<T> *r, int value1, int value2){if (NULL == r)return 0;if (r->data > value1 && r->data > value2)return FLCABST(r->left, value1, value2);if (r->data < value1 && r->data < value2)return FLCABST(r->right, value1, value2);elsereturn r->data;return 0;}

10. 普通二叉树的最低公共祖先(基本思想:默认两个节点都存在,递归求解,遇到一个目标节点则上溯,再对每个节点的左右子树返回结果做判断,只可能有四种情况;对于两个节点在同一分支上的情况,直接返回上一节点。)

template <typename T>BinNode<T> * FLCA(BinNode<T> *r, int value1, int value2){if (NULL == r)return NULL;if (r->data == value1 || r->data == value2)return r;BinNode<T> *left = FLCA(r->left, value1, value2);BinNode<T> *right = FLCA(r->right, value1, value2);if (left == NULL && right == NULL)return NULL;if (left == NULL && right != NULL)return right;if (left !=NULL && right == NULL)return left;elsereturn r;}

11. 判断是否是二叉搜索树

方法一:基本思想:递归的证明左子树最大值小于当前节点值,右子树最小值大于当前节点值

template <typename T>int IsSubBST(BinNode<T> *r, int &min, int &max){if (NULL == r){return 1;}int lmin,lmax,rmin,rmax;if (IsSubBST(r->left,lmin,lmax) && IsSubBST(r->right,rmin,rmax)){if (NULL == r->left && NULL == r->right){min = r->data;max = r->data;return 1;}if (NULL == r->left && r->right != NULL){if (r->data < rmin){min = r->data;max = rmax;return 1;}}if (NULL != r->left && r->right == NULL){if (r->data > lmax){min = lmin;max = r->data;return 1;}}if (NULL != r->left && r->right != NULL){if (r->data > lmax && r->data < rmin){min = lmin;max = rmax;return 1;}}}return 0;}template <typename T>int IsBST(BinNode<T> *r){int min,max;returnIsSubBST(r,min,max);}

方法二:传入两个表示子树范围的参数,递归的证明子树内所有点在这个范围内,并随着递归更新两个范围参数,比方法一简洁很多

template <typename T>int CheckBST(BinNode<T> *r, int min, int max){if (NULL == r)return 1;if (r->data >=min && r->data <= max){return CheckBST(r->left, min, r->data)&&CheckBST(r->right, r->data, max);}return 0;}template <typename T>int IsBST2(BinNode<T> *r){if (NULL == r)return 1;return CheckBST(r, INT_MIN, INT_MAX);}

12. 求二叉树第K层节点个数(根节点为第一层)

template <typename T>int GetNodeCountsKthLevel(BinNode<T> *r, int k){if( r==NULL || k<1)return 0;if ( 1 == k)return 1;int lcount = GetNodeCountsKthLevel(r->left,k-1);int rcount = GetNodeCountsKthLevel(r->left,k-1);return lcount + rcount;}

13. 二叉树节点间的最大距离

template <typename T>int GetSubMaxLength(BinNode<T> *r, int &depth){if (NULL == r){depth = 0;return 0;}int ldepth, rdepth;int lmaxlen, rmaxlen;int maxlen;lmaxlen = GetSubMaxLength(r->left, ldepth);rmaxlen = GetSubMaxLength(r->right, rdepth);depth = ldepth > rdepth ? ldepth + 1 : rdepth + 1;maxlen = ((lmaxlen>rmaxlen?lmaxlen:rmaxlen)>(ldepth+rdepth)) ? (lmaxlen>rmaxlen?lmaxlen:rmaxlen) : (ldepth+rdepth);return maxlen;}template <typename T>int GetMaxLength(BinNode<T> *r){if (NULL == r)return 0;int depth;return GetSubMaxLength(r, depth);}


14. 前序非递归遍历

     第一种方法

template <typename T>void PreOrder_NoRecurse(BinNode<T> *r){stack<BinNode<T> *> s;BinNode<T> *p = r;while (p!=NULL||!s.empty()){while (p!=NULL){cout << p->data << " ";s.push(p);p = p->left;}if (!s.empty()){p = s.top();s.pop();p = p->right;}}}

   第二种方法

template <typename T>void PreOrder_NoRecurse2(BinNode<T> *r){if (NULL == r)return;stack<BinNode<T> *> s;BinNode<T> *p = r;s.push(p);while (!s.empty()){p = s.top();s.pop();cout << p->data << " ";if (p->right != NULL)s.push(p->right);if (p->left != NULL)s.push(p->left);}cout << endl;}

15. 中序非递归遍历

template <typename T>void InOrder_NoRecurse(BinNode<T> *r){stack<BinNode<T> *> s;BinNode<T> *p = r;while (p!=NULL||!s.empty()){while (p!=NULL){s.push(p);p = p->left;}if (!s.empty()){p = s.top();cout << p->data << " ";s.pop();p = p->right;}}}

16. 后序非递归遍历(需要一个标记位,所以重新定义了一个结构体做封装)

template <typename T>struct BTN{BinNode<T> *node;int flag;};
template <typename T>void PostOrder_NoRecurse(BinNode<T> *r){stack<BTN<T> *> s;BinNode<T> *p = r;BTN<T> *temp;while(p!=NULL||!s.empty()){while (p!=NULL){temp = new BTN<T>;temp->node = p;temp->flag = 0;s.push(temp);p = p->left;}if (!s.empty()){temp = s.top();s.pop();if (temp->flag){p = temp->node;cout << p->data << " ";p = NULL;}else{temp->flag = 1;s.push(temp);p = temp->node->right;}}}}

17.判断序列是否是二叉搜索树的后序遍历序列

template <typename T>int IsBSTPostOrder(T a[], int len){if (NULL == a || len <= 0)return 0;for (int index=0; index<len-1; index++){if (a[index] > a[len-1])break;}for (int i=index; i<len-1; i++){if (a[i] < a[len-1])return 0;}int result = 1;if (index > 0)result  = IsBSTPostOrder(a, index);if (result && index < len-1){ result = IsBSTPostOrder(a+index, len-index-1);}return result;}

 

18. 求路径和为给定值的所有路径

template <typename T>void PrintSumPathRecurse(BinNode<T> *r, int k, vector<T> &v){if (NULL == r)return ;k = k - r->data;v.push_back(r->data);if (r->left == NULL && r->right == NULL && k == 0){for (int i=0; i<v.size(); i++)cout << v[i] << " ";cout << endl;}PrintSumPathRecurse(r->left, k, v);PrintSumPathRecurse(r->right, k, v);v.pop_back();}template <typename T>void PrintSumPath(BinNode<T> *r, int k){if (NULL == r)return;vector<T> v;PrintSumPathRecurse(r, k, v);}

19. 判断一二叉树是否是另一二叉树子树

template <typename T>int HasSubTree(BinNode<T> *p, BinNode<T> *q){if (NULL == q)return 1;if (NULL == p)return 0;if (p->data == q->data){return HasSubTree(p->left, q->left)&&HasSubTree(p->right, q->right);}return 0;}template <typename T>int IsSubTree(BinNode<T> *p, BinNode<T> *q){if (NULL == q)return 1;int result = 0;if (p != NULL){if (p->data == q->data)result = HasSubTree(p, q);if (!result)result = IsSubTree(p->left, q); if (!result)result = IsSubTree(p->right, q);}return result;}

20. 根据前序中序遍历重建二叉树

template <typename T>BinNode<T> * RebuildBinTree(T preorder[], T inorder[], int len){if (preorder == NULL || inorder == NULL || len <= 0)return NULL;BinNode<T> *temp = new BinNode<T>;temp->data = preorder[0];for (int i=0; i<len; i++){if (inorder[i] == preorder[0])break;}if (i == len)return NULL;temp->left = RebuildBinTree(preorder+1, inorder, i);temp->right = RebuildBinTree(preorder+i+1, inorder+i+1, len-i-1);return temp;}


21. 判断二叉树结构是否轴对称

template <typename T>int IsSubSymmety(BinNode<T> *p, BinNode<T> *q){ if (NULL == p && NULL == q)return 1;if (NULL == p && q != NULL)return 0;if (p != NULL && NULL == q)return 0;else{return IsSubSymmety(p->left,q->right) && IsSubSymmety(p->right,q->left);}}template <typename T>int IsSymmety(BinNode<T> *r){if (NULL == r)return 1;return IsSubSymmety(r->left, r->right);}


22. 二叉树转换为双向链表

template <typename T>void DoTreeToDouList(BinNode<T> *r, BinNode<T>* &pre){if ( r != NULL){DoTreeToDouList(r->left, pre);  r->left = pre;  if(pre != NULL)  pre->right = r;  pre = r;  DoTreeToDouList(r->right, pre);  }}template <typename T>BinNode<T> * TreeToDouList(BinNode<T> *r){if (NULL == r)return NULL;BinNode<T> *pre = NULL;DoTreeToDouList(r, pre);while(r->left != NULL)r = r->left;return r;}

 

23. 判断两棵二叉树是否结构相同

template <typename T>int IsSameStructure(BinNode<T> *p, BinNode<T> *q){if (NULL == p && NULL == q)return 1;if (NULL == p || q == NULL)return 0;int lresult = IsSameStructure(p->left, q->left);if(lresult){int rresult = IsSameStructure(p->right, q->right);return rresult;}elsereturn lresult;}


24. 求二叉树宽度(节点个数最多的一层有多少个)

template <typename T>int GetWidth(BinNode<T> *r){if (NULL == r)return 0;int width = 0;int temp = 0;int cur = 0;vector<BinNode<T> *> v;v.push_back(r);while (cur < v.size()){temp = 0;int last = v.size();while (cur < last){temp++;if (v[cur]->left != NULL)v.push_back(v[cur]->left);if (v[cur]->right != NULL)v.push_back(v[cur]->right);cur++;}if (temp > width)width = temp;}return width;}

原创粉丝点击