37.序列化二叉树
题目:请实现两个函数,分别用来序列化二叉树和反序列化二叉树
序列化二叉树思路:
第一种方法:可以从前序遍历和中序遍历序列中构造一棵二叉树
缺点:1.该方法要求二叉树中不能有重复的节点
2.只有当两个序列中所有数据都读出来后才开始反序列化,效率较慢
第二种方法:根据前序遍历来序列化二叉树。在遍历二叉树碰到nullptr时,将nullptr序列化为一个特殊的字符
如‘$’。另外数值之间要用‘,’隔开
反序列化二叉树思路:当数据碰到‘$’也就是nullptr时 返回它的父节点,继续遍历下一个节点
<notes>:isotream:1.istream从流中读取
2. ostream写到流中去
fstream:1.ifstream从文件中读取
2.ofstream写道文件中去
sstream:1.istringstream从string对象中读取
2.ostringstream写道string对象中去
#include<iostream>
using namespace std;
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
//序列化
void Serialize(TreeNode* pRoot,ostream& stream){
if(pRoot==nullptr){
stream<<"$,";
return;
}
stream<<pRoot->val<<',';
Serialize(pRoot->left,stream);
Serialize(pRoot->right,stream);
}
//反序列化
void Deserialize(TreeNode**pRoot,istream& stream){
int number;
//ReadStream函数 每次从流中读出一个数字或者一个字符'$'。当从流中读出一个数字时,返回true否则false
if(ReadStream(stream,&number)){
*pRoot=new TreeNode();
(*pRoot)->val=number;
(*pRoot)->left=nullptr;
(*pRoot)->right=nullptr;
Deserialize(&(*pRoot->left),stream);
Deserialize(&(*pRoot->right),stream);
}
}
54.二叉搜索树第k大节点
题目:给定一棵二叉搜索树,请找出其中的第k大的结点。
例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。
思路:根据中序遍历的规律,中序遍历后的数值时递增排序的
注意:指针判空处理
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
TreeNode* KthNode(TreeNode* pRoot, unsigned int k)
{
if(pRoot==NULL||k<=0)
return NULL;
vector<TreeNode*> vec;
Inorder(pRoot,vec);
if(k>vec.size())
return NULL;
return vec[k-1];
}
//中序遍历,将节点依次压入vector中
void Inorder(TreeNode* pRoot,vector<TreeNode*>& vec)
{
if(pRoot==NULL)
return;
Inorder(pRoot->left,vec);
vec.push_back(pRoot);
Inorder(pRoot->right,vec);
}
};
36.二叉树与双向链表
题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
思路:依据中序遍历从小到大的原则 链接左子树最后大的节点和根节点的双向指针和根节点与右子树最小的节点相连接即可
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
TreeNode* Convert(TreeNode* pRootOfTree)
{
//pLastNodeInList指向已经转换好的链表最后一个节点
TreeNode*pLastNodeInList=nullptr;
ConvertNode(pRootOfTree,&pLastNodeInList);
//我们需要返回头节点
TreeNode*pHead=pLastNodeInList;
while(pHead!=nullptr&&pHead->left!=nullptr)
pHead=pHead->left;
return pHead;
}
void ConvertNode(TreeNode*pNode,TreeNode**pLastNodeInList){
if(pNode==nullptr)
return;
TreeNode* pCurrent=pNode;
if(pCurrent->left!=nullptr)
ConvertNode(pCurrent->left,pLastNodeInList);
//链接根节点左右两个指针
//根节点左面的指针指向左子树最后一个节点
pCurrent->left=*pLastNodeInList;
//
if(*pLastNodeInList!=nullptr)
(*pLastNodeInList)->right=pCurrent;
*pLastNodeInList=pCurrent;
if(pCurrent->right!=nullptr)
ConvertNode(pCurrent->right,pLastNodeInList);
}
};