二叉树的序列化和反序列化。
给出一个测试数据样例, 二叉树{3,9,20,#,#,15,7},表示如下的树结构:
主要还是理解完全二叉树的构造,对于节点i,它的左右儿子节点的id分别是2*i+1和2*i+2. 其他都没什么难的,主要是记录code的过程中遇到的坑。
#include
#include
using namespace std;
class TreeNode {
public:
int val;
TreeNode *left, *right;
TreeNode(int val) {
this->val = val;
this->left = this->right = NULL;
}
};
class Solution {
public:
/**
* This method will be invoked first, you should design your own algorithm
* to serialize a binary tree which denote by a root node to a string which
* can be easily deserialized by your own "deserialize" method later.
*/
//最大的节点的编号
int maxNode ;
//处理root当前节点的序列化
void serializeFunc(TreeNode * root,int val[],int Idx){
if(root==NULL)
return;
//计算最大的节点的编号
if(Idx>maxNode)
maxNode = Idx;
val[Idx] = root->val;
int l = Idx*2+1;
int r = Idx*2+2;
if(root->left)
serializeFunc(root->left, val, l);
if(root->right)
serializeFunc(root->right, val, r);
}
string serialize(TreeNode * root) {
// write your code here
int val[10005]={0};
maxNode = -1;
serializeFunc(root, val, 0);
char s[10005]= {};
int s_len = 0;
for(int i=0; i<=maxNode; i++) {
int len;
if (!val[i])
len = snprintf(s+s_len, 100, "%s,", "#");
else
len = snprintf(s+s_len, 100, "%d,", val[i]);
s_len += len;
}
s[s_len-1] = '\0';
string res = s;
return res;
}
/**
* This method will be invoked second, the argument data is what exactly
* you serialized at method "serialize", that means the data is not given by
* system, it's given by your own serialize method. So the format of data is
* designed by yourself, and deserialize it here as you serialize it in
* "serialize" method.
*/
//建立root节点的儿子节点
void ConductTree(TreeNode *root,vector<string> &dArray,int idx,int len){
int l = 2*idx+1;
int r = 2*idx+2;
if(l"#")){
TreeNode *lPoint = new TreeNode(stoi(dArray[l]));
root->left = lPoint;
ConductTree(lPoint, dArray, l, len);
}
if(r"#")){
TreeNode *rPoint = new TreeNode(stoi(dArray[r]));
root->right = rPoint;
ConductTree(rPoint, dArray, r, len);
}
}
vector<string> getDataArray(string data){
vector<string> ret;
char dstr[1005];
strcpy(dstr, data.c_str());
char *p = strtok(dstr, ",");
while(p){
ret.push_back(string(p));
p = strtok(NULL, ",");
}
return ret;
}
TreeNode * deserialize(string &data) {
// write your code here
//string -> string array
vector<string> dArray = getDataArray(data);
int len = dArray.size();
TreeNode * root = NULL;
if(len>0)
root = new TreeNode(stoi(dArray[0]));
ConductTree(root,dArray,0,len);
return root;
}
};
int main() {
// {"1,2,#,1"} {"1,2,3,#,4,#,#,#,#,5,6"} {"3,9,2,#,#,5,7"} {"3,9,20,#,#,1500,700"} {"3,9,20,#,#,15,7"}
string str = {"3,9,20,#,#,1500,700"};
TreeNode * root = Solution().deserialize(str);
string res = Solution().serialize(root);
return 0;
}
char s[] 转string。
char s[1005] = {"012"};
s[4] = '4';
s[5] = '5';
string str = s; // str = "012"
因为s[3] = '\0',所以char s[]转String的时候,碰到第一个'\0'
的时候,就认为字符串结束了。
string str 转char s[]
(JAVA中)由于string是个常量对象,所以string的值是不能修改的。
而C++中的string是可变的!
str.c_str()和str.data()都能得到string的值,二者没有太大区别。但是这两个返回的值都不能直接获得,我们看c_str()的定义,const char *c_str(); c_str()返回的是一个临时指针,不能对其进行操作。
正确的操作方式:
string str = "123";
char s[1005];
strcpy(s, str.c_str());
char s[] 做split操作:
首先,string的函数中也没有split操作,但是有个函数strtok可以对char s[]做split操作。
测试代码如下:
char s[1005] = {"1,2,3,!,!,4,50"};
char sArr[50][1005];
char *tmp;
char *p = strtok_r(s, ",",&tmp);
int cnt=0;
while(p){
strcpy(sArr[cnt++],p);
printf("%s %s\n",p,tmp);
p = strtok_r(NULL, ",", &tmp);
}
返回结果:
1 2,3,!,!,4,50
2 3,!,!,4,50
3 !,!,4,50
! !,4,50
! 4,50
4 50
50 (null)
方法一:snprintf()函数
s[10005];
len = snprintf(s+s_len, 100, "%s,", "#");
第一个参数是写入的起始地址;
第二个参数是写入的最大长度;
第三个参数是写入格式;
第4个参数是写入内容;
返回值是写入的真实长度。
int val[] = {1,2,3,0,0,4,50}
char s[10005]= {};
int s_len = 0;
for(int i=0; i<=maxNode; i++) {
int len;
if (!val[i])
len = snprintf(s+s_len, 100, "%s,", "#");
else
len = snprintf(s+s_len, 100, "%d,", val[i]);
s_len += len;
}
s[s_len] = '\0'
//s = "123##450";
方法二:c++, string 重载了“+”
string q1 = "123";
string q2 = "av";
char q3[100] = {"qq"};
string q4 = "";
q4 = q1+q2+q3 ; // 123avqq
方法三:c, strcat()函数
char p1[100] = {"abc"};
char p2[100] = {"123"};
strcat(p1,p2); // p1: abc123
7.字符串排序
//使用里面的sort函数,这个sort可以对任何数组排序,前两个参数分别是 数组的起止位置,第三个参数是排序方式
string s="123456123";
sort(s.begin(), s.end()); //s: 112233456
//倒序
bool cmp(char x, char y){
return x>y;
}
sort(s.begin(), e.end(), cmp); //s: 654332211
8.c中字符串操作函数:
strlen
strcmp ; strcmp(s1, s2),实际上是 p = s1-s2; 所以p<0,s10,s1==s2, p>0,s1>s2;
strcat
strcpy