算法基础知识——二叉树
算法基础知识——二叉树
目录:
- 基础知识
- 基本定义
- 应用实例
- 重建二叉树【剑指Offer_编程题】
- 二叉树的镜像【剑指Offer_编程题】
- 从上往下打印二叉树【剑指Offer_编程题】
- 二叉搜索树的后续遍历序列【剑指Offer_编程题】
- 二叉树中和为某一值的路径【剑指Offer_编程题】
- 二叉树的深度【剑指Offer_编程题】
- 平衡二叉树【剑指Offer_编程题】
- 二叉搜索树与双向链表【剑指Offer_编程题】
- 对称的二叉树【剑指Offer_编程题】
- 二叉树的下一个结点【剑指Offer_编程题】
- 把二叉树打印成多行【剑指Offer_编程题】
- 二叉搜索树的第k个结点【剑指Offer_编程题】
- 按之字形顺序打印二叉树【剑指Offer_编程题】
- 高度最小的BST【程序员面试金典_ 编程题】
- 输出单层结点【程序员面试金典_ 编程题】
一、基础知识
1、基本定义:
- 度:树中一个结点的子结点的个数称为结点的度,树中结点的最大度数称为树的度。
- 有序树和无序树:
- 有序树:树中结点的子树从左到右是有序的,不能交换。
- 无序树:树中结点的子结点位置可以互换。
- 路径:树中两个结点的路径是由这两个结点之间所经过的结点序列构成的。
- 路径长度:路径上所经过的边的个数。
二、应用实例:
1、题目描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
//write code here
}【剑指Offer_编程题】
- 输入格式:前序遍历序列和中序遍历序列
- 输出格式:重建的二叉树
- 样例输入:无
- 样例输出:无
示例代码:
class Solution {
public:TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin){if(pre.size() == 0 || vin.size() == 0){return NULL;}vector<int> left_pre, right_pre, left_vin, right_vin;TreeNode *head = new TreeNode(pre[0]);int gen = 0;for(int i = 0; i < vin.size(); i++){if(vin[i] == head->val){gen = i;break;}}for(int i = 0; i < gen; i++){left_vin.push_back(vin[i]);left_pre.push_back(pre[i + 1]);}for(int i = gen + 1; i < vin.size(); i++){right_vin.push_back(vin[i]);right_pre.push_back(pre[i]);}head->left = reConstructBinaryTree(left_pre, left_vin);head->right = reConstructBinaryTree(right_pre, right_vin);return head;}
};
2、题目描述:题目描述:操作给定的二叉树,将其变换为源二叉树的镜像。
二叉树的镜像定义:源二叉树
8
/ \
6 10
/ \ / \
5 7 9 11
镜像二叉树
8
/ \
10 6
/ \ / \
11 9 7 5
void Mirror(TreeNode *pRoot) {
//write code here
}【剑指Offer_编程题】
- 输入格式:源二叉树
- 输出格式:镜像二叉树
- 样例输入:无
- 样例输出:无
示例代码:
class Solution {
public:void Mirror(TreeNode *pRoot) {if(pRoot == NULL){return;}TreeNode *p = pRoot->right;pRoot->right = pRoot->left;pRoot->left = p;Mirror(pRoot->right);Mirror(pRoot->left);}
};
3、题目描述:从上往下打印出二叉树的每个节点,同层节点从左至右打印。
vector<int> PrintFromTopToBottom(TreeNode* root) {
//write code here
}【剑指Offer_编程题】
- 输入格式:二叉树根节点指针
- 输出格式:节点列表
- 样例输入:无
- 样例输出:无
示例代码:
/*
struct TreeNode {int val;struct TreeNode *left;struct TreeNode *right;TreeNode(int x) :val(x), left(NULL), right(NULL) {}
};*/
class Solution {
public:vector<int> PrintFromTopToBottom(TreeNode* root) {queue<TreeNode *> myQueue;vector<int> result;if(root != NULL){myQueue.push(root);}while(!myQueue.empty()){TreeNode *current = myQueue.front();myQueue.pop();result.push_back(current->val);if(current->left){myQueue.push(current->left);}if(current->right){myQueue.push(current->right);}}return result;}
};
4、题目描述:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
bool VerifySquenceOfBST(vector<int> sequence) {
//write code here
}【剑指Offer_编程题】
- 输入格式:整型序列
- 输出格式:如果是则输出Yes,否则输出No
- 样例输入:无
- 样例输出:无
示例代码:
class Solution {
public:bool VerifySquenceOfBST(vector<int> sequence){if(sequence.empty()){return false;}int length = sequence.size();if(length == 1){return true;}vector<int> leftSeq, rightSeq;int i = length - 2;while(i >= 0 && sequence[i] > sequence[length - 1]){rightSeq.push_back(sequence[i]);i--;}while(i >= 0 && sequence[i] < sequence[length - 1]){leftSeq.push_back(sequence[i]);i--;}if(i >= 0){return false;}VerifySquenceOfBST(leftSeq);VerifySquenceOfBST(rightSeq);return true;}
};
5、题目描述:输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
//wirte code here
}【剑指Offer_编程题】
- 输入格式:TreeNode* root,int expectNumber
- 输出格式:vector<vector<int> >
- 样例输入:无
- 样例输出:无
示例代码:
class Solution {
public:vector<vector<int> > resultList;vector<int> myVector;vector<vector<int> > FindPath(TreeNode* root,int expectNumber){if(root == NULL){return resultList;}myVector.push_back(root->val);expectNumber -= root->val;if(expectNumber == 0 && root->left == NULL && root->right == NULL){resultList.push_back(myVector);}FindPath(root->left, expectNumber);FindPath(root->right, expectNumber);myVector.erase(myVector.end() - 1);return resultList;}
};
6、题目描述:输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
int TreeDepth(TreeNode* pRoot){
//write code here
}【剑指Offer_编程题】
- 输入格式:根结点指针变量
- 输出格式:树的深度
- 样例输入:无
- 样例输出:无
示例代码:
class Solution {
public:int maxDepth = 0;void CountDepth(TreeNode* pRoot, int count){if(pRoot == NULL){return;}if(pRoot->left == NULL && pRoot->right == NULL){maxDepth = max(maxDepth, count);}CountDepth(pRoot->left, count + 1);CountDepth(pRoot->right, count + 1);}int TreeDepth(TreeNode* pRoot){maxDepth = 0;if(pRoot != NULL){CountDepth(pRoot, 1);}return maxDepth;}
};
7、题目描述:输入一棵二叉树,判断该二叉树是否是平衡二叉树。
bool IsBalanced_Solution(TreeNode* pRoot) {
//write code here
}【剑指Offer_编程题】
- 输入格式:树根结点指针变量
- 输出格式:判断结果
- 样例输入:无
- 样例输出:无
示例代码:
class Solution {
public:vector<int> myVector;void JudgeBST(TreeNode* pRoot){//中序遍历进行判断if(pRoot != NULL){JudgeBST(pRoot->left);myVector.push_back(pRoot->val);JudgeBST(pRoot->right);}}int getDepth(TreeNode *p){if(p == NULL){return 0;}int left = getDepth(p->left);if(left == -1){return -1;}int right = getDepth(p->right);if(right == -1){return -1;}return abs(right - left) > 1 ? -1 : max(right, left) + 1;}bool IsBalanced_Solution(TreeNode* pRoot){if(pRoot == NULL){return true;}//理论上需要先判断是否是一棵二叉排序树/*myVector.clear();JudgeBST(pRoot);for(int i = 1; i < myVector.size(); i++){if(myVector[i] <= myVector[i - 1]){return false;}}*/if(getDepth(pRoot) == -1){return false;}return true;}
};
8、题目描述:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
TreeNode* Convert(TreeNode* pRootOfTree){
//write code here
}【剑指Offer_编程题】
- 输入格式:根结点指针
- 输出格式:排序后的根结点指针
- 样例输入:无
- 样例输出:无
示例代码:
class Solution {
public:void ConvertHelper(TreeNode *cur, TreeNode *&prev){if(cur != NULL){ConvertHelper(cur->left, prev);cur->left = prev;if(prev){prev->right = cur;}prev = cur;ConvertHelper(cur->right, prev);}}TreeNode* Convert(TreeNode *pRootOfTree){if(pRootOfTree == NULL){return pRootOfTree;}TreeNode *prev = NULL;ConvertHelper(pRootOfTree, prev);TreeNode *res = pRootOfTree;while(res->left){res = res->left;}return res;}
};
9、题目描述:请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
bool isSymmetrical(TreeNode* pRoot){
//write code here
}【剑指Offer_编程题】
- 输入格式:根结点指针
- 输出格式:判断是否对称
- 样例输入:无
- 样例输出:无
示例代码1:
class Solution {
public:bool isSymmetrical(TreeNode* pRoot){if(pRoot == NULL){return true;}queue<TreeNode *> myQueue;myQueue.push(pRoot);bool flag = true; //第一次根结点时flag为true,之后列为falsewhile(!myQueue.empty()){TreeNode *leftTree = NULL, *rightTree = NULL;if(flag){ //初始时TreeNode *node = myQueue.front();myQueue.pop();if(node->left != NULL && node->right != NULL){if(node->left->val != node->right->val){return false;}else{myQueue.push(node->left);myQueue.push(node->right);}}flag = false;}else{leftTree = myQueue.front();myQueue.pop();rightTree = myQueue.front();myQueue.pop();if(leftTree->left != NULL && rightTree->right != NULL){if(leftTree->left->val == rightTree->right->val){myQueue.push(leftTree->left);myQueue.push(rightTree->right);}else{return false;}}else if(leftTree->left == NULL && rightTree->right != NULL|| leftTree->left != NULL && rightTree->right == NULL){return false;}if(leftTree->right != NULL && rightTree->left != NULL){ if(leftTree->right->val == rightTree->left->val){myQueue.push(leftTree->right);myQueue.push(rightTree->left);}else{return false;}}else if(leftTree->right == NULL && rightTree->left != NULL|| leftTree->right != NULL && rightTree->left == NULL){ return false;}}}return true;}
};
示例代码2:
class Solution {
public:bool SymmetricalHelper(TreeNode *left, TreeNode *right){if(left == NULL) return right == NULL;if(right == NULL) return false;if(left->val != right->val) return false;return SymmetricalHelper(left->right, right->left) && SymmetricalHelper(left->left, right->right);}bool isSymmetrical(TreeNode *pRoot){if(pRoot == NULL){return true;}return SymmetricalHelper(pRoot->left, pRoot->right);}
};
10、题目描述:给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
/*
struct TreeLinkNode {
int val;
struct TreeLinkNode *left;
struct TreeLinkNode *right;
struct TreeLinkNode *next;
TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {
}
};
*/
TreeLinkNode* GetNext(TreeLinkNode* pNode){}
//write code here
}【剑指Offer_编程题】
- 输入格式:二叉树的其中一个结点
- 输出格式:中序遍历顺序的下一个结点
- 样例输入:无
- 样例输出:无
示例代码1:
class Solution {
public:vector<TreeLinkNode *> nodeList;void InOrder(TreeLinkNode *T){if(T != NULL){InOrder(T->left);nodeList.push_back(T);InOrder(T->right);}}TreeLinkNode* GetNext(TreeLinkNode *pNode){TreeLinkNode *head = NULL, *tmp = pNode;while(tmp->next != NULL){tmp = tmp->next;}head = tmp;nodeList.clear();InOrder(head);for(int i = 0; i < nodeList.size() - 1; i++){if(nodeList[i] == pNode){return nodeList[i + 1];}}return NULL;}
};
示例代码2:
class Solution {
public:TreeLinkNode* GetNext(TreeLinkNode *pNode){if(pNode == NULL){return NULL;}//该结点的右孩子为空if(pNode->right == NULL){//向上找父结点,找到第一个父结点是左孩子则停止while(pNode->next != NULL){if(pNode->next->left == pNode){return pNode->next;}else{pNode = pNode->next;}}}//该结点右孩子不为空else{pNode = pNode->right;while(pNode->left){pNode = pNode->left;}return pNode;}return NULL;}
};
11、题目描述:从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
vector<vector<int> > Print(TreeNode* pRoot) {
//write code here
}【剑指Offer_编程题】
- 输入格式:根结点指针变量
- 输出格式:二维数组,按层输出
- 样例输入:无
- 样例输出:无
示例代码:
class Solution {
public:vector<vector<int> > Print(TreeNode* pRoot) {vector<vector<int> > resultList;if(pRoot == NULL){return resultList;}queue<TreeNode *> myQueue;vector<int> tmpValVector;vector<TreeNode *> tmpVector;myQueue.push(pRoot);while(!myQueue.empty()){tmpVector.clear();tmpValVector.clear();while(!myQueue.empty()){if(myQueue.front()->left != NULL){tmpVector.push_back(myQueue.front()->left);}if(myQueue.front()->right != NULL){tmpVector.push_back(myQueue.front()->right);}tmpValVector.push_back(myQueue.front()->val);myQueue.pop();}resultList.push_back(tmpValVector);for(int i = 0; i < tmpVector.size(); i++){myQueue.push(tmpVector[i]);}}return resultList;}
};
12、题目描述:给定一棵二叉搜索树,请找出其中的第k小的结点。例如,(5,3,7,2,4,6,8)中,按结点数值大小顺序第三小结点的值为4。
TreeNode* KthNode(TreeNode* pRoot, int k){
//write code here
}【剑指Offer_编程题】
- 输入格式:树的根结点指针,整型k
- 输出格式:第k小的结点的指针变量
- 样例输入:无
- 样例输出:无
示例代码1:
class Solution {
public:int index = 0;TreeNode* KthNode(TreeNode* pRoot, int k){if(pRoot){TreeNode *node = KthNode(pRoot->left, k);if(node != NULL){return node;}index++;if(index == k){return pRoot;}node = KthNode(pRoot->right, k);if(node != NULL){return node;}}return NULL;}
};
示例代码2:
class Solution {
public:vector<TreeNode *> resultList;void InOrder(TreeNode* pRoot){if(pRoot != NULL){InOrder(pRoot->left);resultList.push_back(pRoot);InOrder(pRoot->right);}}TreeNode* KthNode(TreeNode* pRoot, int k){if(k <= 0 || pRoot == NULL){return NULL;}resultList.clear();InOrder(pRoot);if(k > resultList.size()){return NULL;}return resultList[k - 1];}
};
13、题目描述:请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
vector<vector<int> > Print(TreeNode* pRoot){
//write code here
}【剑指Offer_编程题】
- 输入格式:根结点指针变量
- 输出格式:二维数组,按层输出
- 样例输入:无
- 样例输出:无
示例代码:
class Solution {
public:vector<vector<int> > Print(TreeNode* pRoot){vector<vector<int> > resultList;if(pRoot == NULL){return resultList;}int level = 1;queue<TreeNode *> myQueue;myQueue.push(pRoot);while(!myQueue.empty()){vector<int> tmpValVector;vector<TreeNode *> tmpNodeVector;while(!myQueue.empty()){TreeNode *node = myQueue.front();myQueue.pop();tmpValVector.push_back(node->val);if(node->left != NULL){tmpNodeVector.push_back(node->left);}if(node->right != NULL){tmpNodeVector.push_back(node->right);}}if(level % 2 == 0){reverse(tmpValVector.begin(), tmpValVector.end());}resultList.push_back(tmpValVector);for(int i = 0; i < tmpNodeVector.size(); i++){myQueue.push(tmpNodeVector[i]);//从左到右入结点}level++;}return resultList;}
};
14、题目描述:对于一个元素各不相同且按升序排列的有序序列,请编写一个算法,创建一棵高度最小的二叉查找树。给定一个有序序列int[] vals,请返回创建的二叉查找树的高度。
int buildMinimalBST(vector<int> vals) {
// write code here
}【程序员面试金典_ 编程题】
- 输入格式:有序序列
- 输出格式:高度值
- 样例输入:无
- 样例输出:无
示例代码:
class MinimalBST {
public:int buildMinimalBST(vector<int> vals) {int length = vals.size();int count = 0;while(length > 0){count++;length /= 2;}return count;}
};
15、题目描述:对于一棵二叉树,请设计一个算法,创建含有某一深度上所有结点的链表。给定二叉树的根结点指针TreeNode* root,以及链表上结点的深度,请返回一个链表ListNode,代表该深度上所有结点的值,请按树上从左往右的顺序链接,保证深度不超过树的高度,树上结点的值为非负整数且不超过100000。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
ListNode* getTreeLevel(TreeNode* root, int dep){
//write code here
}【程序员面试金典_ 编程题】
- 输入格式:根结点指针变量,深度值
- 输出格式:含有某一深度上所有结点的链表
- 样例输入:无
- 样例输出:无
示例代码:
class TreeLevel {
public:ListNode* getTreeLevel(TreeNode* root, int dep){if(root == NULL || dep <= 0){return NULL;}ListNode *head = new ListNode(-1);ListNode *p = head;queue<TreeNode *> myQueue;myQueue.push(root);int curr = 1;while(!myQueue.empty()){vector<TreeNode *> tmpVector;while(!myQueue.empty()){TreeNode *node = myQueue.front();myQueue.pop();if(curr == dep){p->next = new ListNode(node->val);p = p->next;}else{if(node->left){tmpVector.push_back(node->left);}if(node->right){tmpVector.push_back(node->right);}}}for(int i = 0; i < tmpVector.size(); i++){myQueue.push(tmpVector[i]);}curr++;}return head->next;}
};
算法基础知识——二叉树相关推荐
- 【Java面试高频问题】Java数据结构和算法基础知识汇总
文章目录 Java数据结构和算法基础知识 一.Java数据结构 1. 线性结构:数组.队列.链表和栈 1.1 数组(Array) 1.2 稀疏数组 1.3 队列(Queue) 1.4 链表(Linke ...
- 算法基础之二叉树理论
算法基础之二叉树理论 1.树基础 2.二叉树基础 3.二叉树基本操作 3.1插入结点 3.2二叉树遍历 3.2.1 深度优先遍历 3.2.2 广度优先遍历 1.树基础 官方定义:树是n(n>=0 ...
- 算法基础知识总结(基础算法)
算法基础知识总结 Efficient procedures for solving problems on large inputs. 一.基础算法 1.快速排序 1.类别:快速排序是一种 交换排序, ...
- 算法基础知识——动态规划
算法基础知识--动态规划 目录: 基础知识 分治法和动态规划的区别 动态规划算法设计步骤 最优子结构性质定义 动态规划两种等价的实现方法(自顶向下带备忘.自底向上) 子问题图 经典问题 钢条切割 矩阵 ...
- 【数据结构与算法基础】二叉树与其遍历序列的互化 附代码实现(C和java)
前言 数据结构,一门数据处理的艺术,精巧的结构在一个又一个算法下发挥着他们无与伦比的高效和精密之美,在为信息技术打下坚实地基的同时,也令无数开发者和探索者为之着迷. 也因如此,它作为博主大二上学期最重 ...
- 算法基础知识科普:8大搜索算法之红黑树(下)
这是介绍红黑树的最后一部分,令y为要删除结点,n为要删除结点的子结点(子结点最多有1个),w为y的兄弟结点,删除操作的重点是使红黑树删除结点并通过调整后仍满足自身是搜索二叉树和设定的三点规则.删除操作 ...
- 算法基础知识科普:8大搜索算法之二叉搜索树(下)
由于微信发代码以及数学符号很吃力,所以我们做知识科普只能利用图片来做,本算法代码较多,所以分为三个部分来介绍.本篇把剩余的部分补齐.当然二叉搜索树也有自己的缺陷,即构造的二叉树跟数据的初始状态以及删除 ...
- 机器学习算法基础知识
在我们了解了需要解决的机器学习问题的类型之后,我们可以开始考虑搜集来的数据的类型以及我们可以尝试的机器学习算法.在这个帖子里,我们会介绍一遍最流行的机器学习算法.通过浏览主要的算法来大致了解可以利用的 ...
- 算法基础知识科普:8大搜索算法之红黑树(上)
平衡二叉树(AVL)是一种特殊的二叉搜索树(BST),即每个结点的值都大于其左子树且小于其右子树的值(若存在),并通过引入平衡因子的概念来保持树的平衡.平衡二叉树算法的重点是在插入.删除结点时,如何保 ...
最新文章
- CodeForces - 1337E Kaavi and Magic Spell(dp)
- P1494 [国家集训队]小Z的袜子
- LintCode-244.删除字符
- 阿里电商架构演变之路(一)
- Atitit 互联网技术公司防爆指南技术规范标准流程 30个危险物品
- 有没有那种免费的办公软件?
- Android 查看是否支持指定解码器(H265)
- user guide for Coverity Wizard
- Go reflect初探
- centos安装LDAP即配置
- CAD“左手键”快捷命令表,大大提高绘图效率
- android与ios ui切图关系,iOS、Android 开发单位换算及 UI 切图要求
- 带联网功能的RFID宿舍门禁(四)-NodeMCU网站与RC522共同控制舵机转动
- git命令切换分支、更新分支
- Java 实现手机短信发送
- html5视频播放av,7月AHA急救课程报名中!掌握埃里克森心脏骤停的获救技能!!...
- IBMMQ创建带权限验证的消息队列
- 猜数字游戏(C语言生成随机数)
- 如何自己制作一个路由器?
- ClassNotFoundException: org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver