二叉树
1.二叉树搜索树与双向链表(剑指offer 36)
题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
解题思路:
- 首先明白二叉搜索树的原理,每个结点的左结点均小于根节点,右节点均大于根节点,故转为排序的双向链表实际上是对二叉搜索树进行中序遍历,采用递归思想。
- 创建一个链表的根节点pListLastNode来记录当前链表指向的位置,同时与树节点的当前节点pTreeNode调整指针关系,树当前节点的左结点指向链表根节点,链表根节点的右节点指向树的当前节点,根据中序遍历思想依次建立指针关系。
- 当遍历到根节点时,此时pListLastNode指向左子树最大的结点,与根节点建立双向连接之后,再去找右子树最小的结点建立连接,之后右子树遍历直到最后一个节点。
- 从链表尾结点循环找到头结点,返回链表头结点。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
void convertTree(TreeNode* pTreeNode,TreeNode** pListLastNode)
{
if(pTreeNode==nullptr)
return;
if(pTreeNode->left!=nullptr)
convertTree(pTreeNode->left,pListLastNode);
pTreeNode->left=*pListLastNode;
if(*pListLastNode!=nullptr)
(*pListLastNode)->right=pTreeNode;
*pListLastNode=pTreeNode;
if(pTreeNode->right!=nullptr)
convertTree(pTreeNode->right,pListLastNode);
}
TreeNode* Convert(TreeNode* pRootOfTree)
{
TreeNode* pListLastNode=nullptr;
convertTree(pRootOfTree,&pListLastNode);
TreeNode* pHeadList=pListLastNode;
while(pHeadList!=nullptr && pHeadList->left!=nullptr)
pHeadList=pHeadList->left;
return pHeadList;
}
};
2.序列化二叉树(剑指offer 37)
题目描述:
请实现两个函数,分别用来序列化和反序列化二叉树
二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。
二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。
解题思路:
序列化
- 对于序列化二叉树来说,采用前序遍历根左右来递归输出字符串。当结点为空时,string字符串添加‘#’,当字符不为空时,添加当前值以及一个分隔符‘!’,遍历左子树和右子树,最终输出一个序列化的字符串。(要注意char* 和 string 以及 int 的相互转换)
反序列化
注意此处要使用二级指针,否则指向字符串的指针不能依次向后移动。
- 从起始位置访问序列,当指向‘#’时,返回节点为NULL,当指向数字时,要判断下一位是否还是数字以及是否指向字符串末尾,例如300要循环三次将字符串转为整数并且创建新的节点,之后将指针位置向后移动,递归访问左右子树,完成反序列化。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
void serialize(TreeNode *root, string& s)
{
if (root == NULL)
{
s+="#";
return;
}
s += to_string(root->val)+'!';
serialize(root->left, s);
serialize(root->right, s);
}
char* Serialize(TreeNode *root) {
if(root==NULL)
return NULL;
string s;
serialize(root, s);
char* res = new char[s.length() + 1];
int i;
for (i=0 ; i<s.size(); i++)
{
res[i] = s[i];
}
res[i] = '\0';
return res;
}
TreeNode* deserialize(char** str)
{
if (**str == '#')
{
++(*str);
return NULL;
}
int num = 0;
while (**str != '\0' && **str != '!')
{
num = num * 10 + ((**str) - '0');
++(*str);
}
TreeNode* root = new TreeNode(num);
if ((**str) == '\0')
return root;
else
++(*str);
root->left = deserialize(str);
root->right = deserialize(str);
return root;
}
TreeNode* Deserialize(char *str) {
if (str == NULL)
return NULL;
return deserialize(&str);
}
};
3.二叉树的镜像(剑指offer 27)
题目描述:输入一颗二叉树,该函数输出它的镜像。
解题思路:递归遍历解决。
- 先序遍历每个结点,若节点为空节点,或者为叶子结点返回。
- 对每个非空非叶子节点交换左右结点。
- 通过根左右依次遍历,交换所有结点,得到镜像。
class Solution {
public:
void invert(TreeNode* root) {
if(root==nullptr)
return;
if(root->left==nullptr && root->right==nullptr)
return;
TreeNode* tmp=root->left;
root->left=root->right;
root->right=tmp;
invertTree(root->left);
invertTree(root->right);
}
TreeNode* invertTree(TreeNode* root) {
invert(root);
return root;
}
};