c++二叉树构建及面试常见问题代码实现
来源:互联网 发布:汤臣一品 知乎 编辑:程序博客网 时间:2024/06/06 13:38
二叉树的面试常见问题包括:
参考文章:
- 二叉树中的节点个数
- 二叉树的深度
- 前序遍历,中序遍历,后序遍历,层序遍历
- 将二叉查找树变为有序的双向链表
- 二叉树第K层的节点个数
- 二叉树中叶子节点的个数
- 判断二叉树是不是平衡二叉树
- 二叉树的镜像
- 二叉树中两个节点的最低公共祖先节点
- 二叉树中节点的最大距离
- 判断二叉树是不是完全二叉树
下面是完整二叉树及这些常见问题的代码实现:
头文件BTree.h
#ifndef BTREE_H#define BTREE_Hstruct BTreeNode{int data;BTreeNode *lChild,*rChild;};class BTree{public:void setRoot(BTreeNode* r){ root=r;}BTreeNode* getRoot(){ return root;}BTreeNode* createBTree();BTree():root(createBTree()){}//中序遍历(递归)void inOrder();//中序遍历(非递归)void NotReInOrder();//前序遍历(递归)void preOrder();//前序遍历(非递归)void NotRePreOrder();//后序遍历(递归)void postOrder();//后序遍历(非递归)void NotRePostOrder();//层序遍历BFS void LevelOrder(BTreeNode*); //求结点个数int BTreeSize();//求叶子结点个数int BTreeLeaves();//求树高int BTreeHeight();//将二叉查找树变为有序的双向链表void convert_tree_list(BTreeNode * pRoot, BTreeNode * & pFirstNode, BTreeNode * & pLastNode); //二叉树第k层节点个数int GetNodeNumKthLevel(BTreeNode * pRoot, int k);//判断二叉树是否是平衡的bool IsAVL(BTreeNode * pRoot,int & height); //求二叉树的镜像BTreeNode * Mirror(BTreeNode * pRoot); //判断一个节点是否存在 bool FindNode(BTreeNode * pRoot, BTreeNode * pNode);// 求二叉树两个节点的公共祖先BTreeNode * GetLastCommonParent(BTreeNode * pRoot, BTreeNode * pNode1, BTreeNode * pNode2); //求二叉树节点的最大距离 int GetMaxDistance(BTreeNode * pRoot, int & maxLeft, int & maxRight); //判断一颗树是不是完全二叉树bool IsCompleteBinaryTree(BTreeNode * pRoot); protected://中序遍历void inOrder(BTreeNode*);//前序遍历void preOrder(BTreeNode*);//后序遍历void postOrder(BTreeNode*);//结点个数int BTreeSize(BTreeNode*);//叶子结点int BTreeLeaves(BTreeNode*);//树高int BTreeHeight(BTreeNode*);private:BTreeNode* root;};#endif源文件BTree.cpp
#include <iostream>#include <stack>#include <queue>#include <algorithm>#include "BTree.h"using namespace std;//建立二叉树的算法BTreeNode* BTree::createBTree(){BTreeNode* current=0;int val=0;cin>>val;//-1的个数比数值的个数多1if(val==-1)return NULL;else{current=new BTreeNode;current->data=val;current->lChild=createBTree();current->rChild=createBTree();return current;}}//利用重载的方法void BTree::inOrder(){inOrder(root);cout<<endl;}//中序访问二叉树(递归)void BTree::inOrder(BTreeNode* r){if(r!=0) //是if,而不是while{inOrder(r->lChild); //递归访问cout<<r->data<<" ";inOrder(r->rChild); //递归访问}}//中序遍历(非递归)//往左放,放完访问,回溯到右 void BTree::NotReInOrder(){stack<BTreeNode*> s;BTreeNode* r=getRoot();while(!s.empty()||r!=0){while(r!=0){s.push(r);r=r->lChild;}if(!s.empty()){r=s.top();s.pop();cout<<r->data<<" ";r=r->rChild;}}}//重载形式void BTree::preOrder(){preOrder(root);cout<<endl;}//前序递归访问二叉树(递归)void BTree::preOrder(BTreeNode* r){if(r!=0) //是if,而不是while{cout<<r->data<<" ";preOrder(r->lChild); //递归访问preOrder(r->rChild); //递归访问}}//前序遍历(非递归)//过程可以理解为:放入一个元素,访问它,弹出,//放入她的右孩子以便返回,放入左孩子用于下次访问 void BTree::NotRePreOrder(){stack<BTreeNode*> s;BTreeNode* r=getRoot();s.push(r);while(!s.empty()){r=s.top();s.pop();cout<<r->data<<" ";if(r->rChild!=0)s.push(r->rChild);if(r->lChild!=0)s.push(r->lChild);}}//重载形式void BTree::postOrder(){postOrder(root);cout<<endl;}//后序遍历(递归)void BTree::postOrder(BTreeNode* r){if(r!=0) //是if,而不是while{postOrder(r->lChild); //递归访问postOrder(r->rChild); //递归访问cout<<r->data<<" ";}}//后序非递归访问要定义新的结构体类型struct Node{BTreeNode* tp;bool flag;};//后序遍历(非递归)void BTree::NotRePostOrder(){Node node; //定义Node结构体的一个结点stack<Node> s;BTreeNode* r=getRoot();while(!s.empty()||r!=0){while(r!=0){node.tp=r;node.flag=0;s.push(node);r=r->lChild;}if(!s.empty()){node=s.top();s.pop();r=node.tp; //将栈顶的BTreeNode*部分赋给rif(node.flag==1){cout<<r->data<<" ";r=0; //表示已经访问了该结点}else{node.flag=1;s.push(node);r=r->rChild;}}}}//层序遍历,即广度优先搜索,用到queue void BTree::LevelOrder(BTreeNode* pRoot) { if(pRoot == NULL) return; queue<BTreeNode *> q; q.push(pRoot); while(!q.empty()) { BTreeNode * pNode = q.front(); q.pop(); cout<<pNode->data; // 访问节点 if(pNode->lChild != NULL) q.push(pNode->lChild); if(pNode->rChild != NULL) q.push(pNode->rChild); }}//重载形式int BTree::BTreeSize(){return BTreeSize(root);}//求二叉树结点个数的函数int BTree::BTreeSize(BTreeNode* r){//二叉树的结点个数为左右子树的高度之和再+1if(r==0) return 0; elsereturn 1+BTreeSize(r->lChild)+BTreeSize(r->rChild);}//重载形式int BTree::BTreeLeaves(){return BTreeLeaves(root);}//求二叉树叶子结点个数的函数int BTree::BTreeLeaves(BTreeNode* r){//当为空时,返回0;当找到叶子时返回1if(r==0) return 0; else if(r->lChild==0&&r->rChild==0)return 1;elsereturn BTreeLeaves(r->lChild)+BTreeLeaves(r->rChild);}//重载形式int BTree::BTreeHeight(){return BTreeHeight(root);}//求二叉树高度的函数int BTree::BTreeHeight(BTreeNode* r){if(r==0) return 0;//二叉树的高度为左右子树的最大者+1elsereturn max(BTreeHeight(r->lChild),BTreeHeight(r->rChild))+1;}void BTree::convert_tree_list(BTreeNode * pRoot, BTreeNode * & pFirstNode, BTreeNode * & pLastNode){ BTreeNode *pLastLeft, * pFirstRight; if(pRoot == NULL) { pFirstNode = NULL; pLastNode = NULL; return; } if(pRoot->lChild == NULL) { // 如果左子树为空,对应双向有序链表的第一个节点是根节点 pFirstNode = pRoot; } else { convert_tree_list(pRoot->lChild, pFirstNode, pLastLeft); // 将根节点和左子树转换后的双向有序链表的最后一个节点连接 pRoot->lChild = pLastLeft; pLastLeft->rChild = pRoot; } if(pRoot->rChild == NULL) { // 对应双向有序链表的最后一个节点是根节点 pLastNode = pRoot; } else { convert_tree_list(pRoot->rChild, pFirstRight, pLastNode); // 将根节点和右子树转换后的双向有序链表的第一个节点连接 pRoot->rChild = pFirstRight; pFirstRight->lChild = pRoot; } } //二叉树第k层节点个数int BTree::GetNodeNumKthLevel(BTreeNode * pRoot, int k) { if(pRoot == NULL || k < 1) return 0; else if(k == 1) return 1; else return (GetNodeNumKthLevel(pRoot->lChild, k-1) + GetNodeNumKthLevel(pRoot->rChild, k-1)); } //判断二叉树是否是平衡的bool BTree::IsAVL(BTreeNode * pRoot,int & height){if(pRoot == NULL) // 空树,返回真 { height = 0; return true; } int heightLeft; bool resultLeft = IsAVL(pRoot->lChild, heightLeft); int heightRight; bool resultRight = IsAVL(pRoot->rChild, heightRight); if(resultLeft && resultRight && abs(heightLeft - heightRight) <= 1) // 左子树和右子树都是AVL,并且高度相差不大于1,返回真 { height = max(heightLeft, heightRight) + 1; return true; } else { height = max(heightLeft, heightRight) + 1; return false; } }//求二叉树的镜像BTreeNode * BTree::Mirror(BTreeNode * pRoot){if(pRoot == NULL) return NULL; // 交换左子树和右子树 pRoot->lChild = Mirror(pRoot->rChild); pRoot->rChild = Mirror(pRoot->lChild); return pRoot; } //判断一个节点是否存在 bool BTree::FindNode(BTreeNode * pRoot, BTreeNode * pNode){if(pRoot == NULL || pNode == NULL) return false; else if(pRoot == pNode) return true; else return FindNode(pRoot->lChild, pNode)||FindNode(pRoot->rChild, pNode); }// 求二叉树两个节点的公共祖先BTreeNode * BTree::GetLastCommonParent(BTreeNode * pRoot, BTreeNode * pNode1, BTreeNode * pNode2){bool lf1=FindNode(pRoot->lChild,pNode1);bool lf2=FindNode(pRoot->lChild,pNode2);bool rf1=FindNode(pRoot->rChild,pNode1);bool rf2=FindNode(pRoot->rChild,pNode2);if(lf1&&lf2) return GetLastCommonParent(pRoot->lChild,pNode1,pNode2);else if(rf1&&rf2) return GetLastCommonParent(pRoot->rChild,pNode1,pNode2);else return pRoot;}//求二叉树节点的最大距离 //用到分治策略 int BTree::GetMaxDistance(BTreeNode * pRoot, int & maxLeft, int & maxRight){// maxLeft, 左子树中的节点距离根节点的最远距离 // maxRight, 右子树中的节点距离根节点的最远距离 if(pRoot == NULL) { maxLeft = 0; maxRight = 0; return 0; } int maxLL, maxLR, maxRL, maxRR; int maxDistLeft, maxDistRight; if(pRoot->lChild != NULL) { maxDistLeft = GetMaxDistance(pRoot->lChild, maxLL, maxLR); maxLeft = max(maxLL, maxLR) + 1; } else { maxDistLeft = 0; maxLeft = 0; } if(pRoot->rChild != NULL) { maxDistRight = GetMaxDistance(pRoot->rChild, maxRL, maxRR); maxRight = max(maxRL, maxRR) + 1; } else { maxDistRight = 0; maxRight = 0; } return max(max(maxDistLeft, maxDistRight), maxLeft+maxRight); } //判断一颗树是不是完全二叉树// 按层序遍历,当遇到一个节点的左子树为空时,则该节点右子树必须为空且后面节点的左右子树都为空// 当遇到右子树为空,则后面节点左右子树都为空 bool BTree::IsCompleteBinaryTree(BTreeNode * pRoot) { if(pRoot == NULL) return false; queue<BTreeNode *> q; q.push(pRoot); bool mustHaveNoChild = false; bool result = true; while(!q.empty()) { BTreeNode * pNode = q.front(); q.pop(); if(mustHaveNoChild) // 已经出现了有空子树的节点了,后面出现的必须为叶节点(左右子树都为空) { if(pNode->lChild != NULL || pNode->rChild != NULL) { result = false; break; } } else { if(pNode->lChild != NULL && pNode->rChild != NULL) { q.push(pNode->lChild); q.push(pNode->rChild); } else if(pNode->lChild != NULL && pNode->rChild == NULL) { mustHaveNoChild = true; q.push(pNode->rChild); } else if(pNode->lChild == NULL && pNode->rChild != NULL) { result = false; break; } else { mustHaveNoChild = true; } } } return result; }
参考文章:
http://blog.csdn.net/luckyxiaoqiang/article/details/7518888/
http://blog.csdn.net/iqrocket/article/details/8266365#cpp
1 0
- c++二叉树构建及面试常见问题代码实现
- C语言实现构建二叉树
- 二叉树数组实现[C/C++]代码
- 二叉树的构建及遍历 Java实现
- 二叉树的性质及实现代码 !!!!
- 二叉搜索树 及 c++代码实现
- 二叉查找树C实现代码
- 二叉树链式结构C代码实现
- 二叉树线索化C代码实现
- 构建二叉树及遍历
- 二叉树遍历及C语言实现
- 二叉树遍历及C语言实现
- 二叉树遍历及C语言实现
- 二叉树遍历及C语言实现
- c原生实现二叉树的构建和 非递归遍历二叉树的方法
- c语言面试常见问题
- 二叉树实现代码
- 二叉树的构建及各种遍历
- POJ 3259 Wormholes SPFA判负环
- 饥饿的小易
- Android学习-Sax解析XML
- 【PAT】(乙级)1006. 换个格式输出整数 (15)
- OpenCV+OpenGL 双目立体视觉三维重建
- c++二叉树构建及面试常见问题代码实现
- C语言总结
- 蓝鸥啊
- Spark优化及总结
- dojo中form应用示例
- PHP运行出现Notice : Notice: Undefined index的原因及解决办法
- scala学习笔记9 继承
- HDU 2199 Can you solve this equation?(二分算法)
- 【PAT】(乙级)1007. 素数对猜想 (20)