力扣第 297 题「 二叉树的序列化与反序列化」、stringstream的用法、getline用法

力扣第 297 题「 二叉树的序列化与反序列化

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Codec {
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        
    }
};

// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));

总结结论

  1. 如果你的序列化结果中不包含空指针的信息,且你只给出一种遍历顺序,那么你无法还原出唯一的一棵二叉树。

  2. 如果你的序列化结果中不包含空指针的信息,且你会给出两种遍历顺序,那么按照前文 东哥手把手带你刷二叉树(构造篇) 所说,分两种情况:

    2.1. 如果你给出的是前序和中序,或者后序和中序,那么你可以还原出唯一的一棵二叉树。

    2.2. 如果你给出前序和后序,那么除非你的整棵树中不包含值相同的节点,否则你无法还原出唯一的一棵二叉树。

  3. 如果你的序列化结果中包含空指针的信息,且你只给出一种遍历顺序,也要分两种情况:

    3.1. 如果你给出的是前序或者后序,那么你可以还原出唯一的一棵二叉树。

    3.2. 如果你给出的是中序,那么除非你的整棵树中不包含值相同的节点,否则你无法还原出唯一的一棵二叉树。

class Codec {
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        if(root==NULL) return "#,";

        string res = to_string(root->val)+",";

        res += serialize(root->left);
        res += serialize(root->right);
        return res;
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        stringstream ss(data);
        string item;
        queue<string> q;
        while (getline(ss, item, ',')) 
            q.push(item);
        return helper(q);
    }
    //辅助函数
    TreeNode* helper(queue<string>& q)
    {
        string val = q.front();
        q.pop();
        if (val == "#")
            return NULL;
        TreeNode* head = new TreeNode(stoi(val));
        head->left = helper(q);
        head->right = helper(q);
        return head;
    }
};

stringstream的用法

一、概念

stringstream 是 C++ 标准库中的一个流类,可以用于将字符串当做流来处理。stringstream 可以对字符串进行输入输出、格式化、类型转换等操作,常用于字符串解析、格式化输出、类型转换等场景。

原文链接:stringstream用法总结_子木呀的博客-CSDN博客

C++ stringstream 类是一种十分有用的类,特别是当我们需要在程序中使用字符串和数字数据的时候。要想在程序中使用 stringstream 类,我们需要在源程序文件中包含头文件include<sstream>。stringstream 对象的使用方法与cout对象的使用方法基本相同。stringstream 类提供的函数,将数字化转化为字符串。

当我们需要按预定的格式将程序中的数据保存在一个string 中的时候,可以先创建一个stringstream 对象,并通过运算符 ”<<“ 将数据传递给 stringstream 对象。(这与通过”<<“ 使用cout 对象的方法相同。)接着,我们可以通过调用stringstream 类的函数str() 将对象所包含的内容赋给一个string对象。在一下的程序中,我们先将数据传递给一个stringstream 对象,然后通过该 stringstream 对象将数值赋给一个string 对象。

二、基本功能

功能一、预定的格式将程序中的数据保存在一个string中

// 如何使用 stringstream 
// 对象生成格式化的 string
 
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
 
int main()
{
	cout << "\n Welcome to the StringStream Demo program.\n";
 
	// 构建一些将在string中出现的数据变量
	// PI 精确到小数点后15位
	double pi = 3.141592653589793;
	float dollar = 1.00;
	int dozen = 12;
 
	string text;
 
	// 我们希望tring 的格式如下:
	// dozen适12,dollar是$1.00
	// 精确到小数点后10为pi是3.141592653589793
 
	// 生成stringstream 对象
	stringstream ss;
	
	// 现在像使用cout一样使用ss
 
	ss << " A dozen is "<< dozen << ", a dollar is $ ";
	ss.setf(ios::fixed);
	ss.precision(2);
	ss << dollar << " and \n the value of pi to 10 places is ";
	ss.precision(10);
	ss << pi << ".";
 
	// 现在将ss中的内容赋给一个string对象
	// 使用str()函数
 
	text = ss.str();
	cout << "\nHere is our formatted text string:\n" << text << endl;
	// 再加入一些信息
	ss << "\ There are 2 \"+\" in C++.";
	text = ss.str();
	cout<< "\nHere is the final string:\n" << text << endl;
	return 0;
}

stringstream类常用的成员函数

ss.str(); 读取对象中的字符串内容

ss.clear(); 清除当前对象的状态

ss.setf(ios::fixed); stringstream 类的一个成员函数,用于设置流格式标志,即指定流的输出格式。在这里,ios::fixed 是一个枚举值,表示输出浮点数时按照定点格式输出。

具体来说,当使用 ios::fixed 标志时,浮点数的输出格式将被固定,小数部分将保留指定的位数(默认是 6 位),即使小数部分为 0。这与默认的浮点数格式 ios::scientific 不同,后者将自动选择科学计数法输出浮点数,根据数值的大小自动确定精度。

在代码中,ss.setf(ios::fixed); 的作用是将 stringstream 对象 ss 的输出格式设置为定点格式,这样在输出浮点数时,小数点后的位数将保留指定的精度。这个设置通常与 setprecision() 函数一起使用,后者用于指定输出的小数点后的位数。

ss.precision(2); 是 stringstream 类的一个成员函数,用于设置浮点数输出的精度,即小数点后的位数。在这里,参数 2 表示输出浮点数时小数点后保留 2 位。

具体来说,当使用 ss.precision(2) 时,输出浮点数时,小数点后的位数将保留 2 位。例如,输出 3.14159265358979323846 时,将会输出 3.14。

功能二、实现类型转换

#include <iostream>
#include <string>
#include <sstream>
using namespace std;
 
int main()
{
	double  rb;  
	int     ri;     // 存储结果
	string  s;      // 要转化的字符串
	stringstream ss;
	s = "123.456789";
	ss << s;         // 类似 cout
	ss >> rb;        // 类似 cin
	cout.precision(10);
	cout << "string \""<< s << "\" to double object " 
		<< rb << endl;
	s = "654321";
	ss.clear();      //清空流
	ss << s;
	ss >> ri;
	cout << "string \""<< s << "\" to int object " 
		<< ri << endl;
	return 0;
}

三、重要功能

1.数字由空格或者都好分开

#include<iostream>
#include<sstream>
#include<vector>
using namespace std;

int main() {
	stringstream ss;
	vector<int> nums;
	string input;
	getline(cin, input);
	ss << input;
	int num;
	while (ss >> num) { //读取的时候自动将string型转换成int型
		nums.push_back(num);
	}
	for (auto a : nums) {
		cout << a << endl;
	}
	return 0;
}
//因为stringstream默认输出由空格分开 

下面是一个简单的示例,展示了如何使用 stringstream 类来进行字符串流的输入输出操作:

#include <iostream>
#include <sstream>
#include <string>

int main() {
    std::string str = "Hello World";
    std::stringstream ss;
    ss << str;  // 将字符串写入 stringstream 对象中
    std::string str_out;
    ss >> str_out;  // 从 stringstream 对象中读取字符串
    std::cout << str_out << std::endl;  // 输出读取到的字符串
    return 0;
}

在上面的代码中,我们首先创建了一个字符串 str,然后创建了一个 stringstream 对象 ss。将字符串 str 写入 ss 中,然后从 ss 中读取字符串到变量 str_out 中,并使用 cout 流输出 str_out 的值。(只读取了前面的一个字符串,如果加上while循环就会自动读取ss中的以空格分开的所有字符串)

输出结果为:

Hello

2.数字由逗号分开

#include<iostream>
#include<sstream>
#include<vector>
using namespace std;

int main() {
	stringstream ss;
	vector<int> nums;
	string input;
	getline(cin, input);
	ss << input;
	string num;
	while (getline(ss, num, ',')) {
		nums.push_back(stoi(num));
	}
	for (auto a : nums) {
		cout << a << endl;
	}
	return 0;
}

stoi 用法链接:【最贴心】C++字符串转换(stoi;stol;stoul;stoll;stoull;stof;stod;stold)_来老铁干了这碗代码的博客-CSDN博客

getline用法

getline 是 C++ 标准库中用于从输入流中读取一行数据的函数。其基本语法如下:

istream& getline(istream& is, string& str, char delim);

其中,is 是输入流对象,str 是存储读取数据的字符串对象,delim 是行分隔符(默认为 \n)。函数将从输入流对象 is 中读取一行数据,存储到字符串对象 str 中,直到遇到行分隔符为止(或者到达文件末尾)。最后,函数将返回输入流对象 is 的引用。

例如,下面的代码从标准输入流中读取一行数据,并将其存储到字符串变量 input 中:

string input;
getline(cin, input);

在这个例子中,cin 是标准输入流对象,input 是存储读取数据的字符串对象。函数 getline(cin, input) 从标准输入流对象 cin 中读取一行数据,存储到字符串变量 input 中。如果输入流对象 cin 已经到达文件末尾,函数将返回 cin 的引用,即 cin 的值为 false

getline 函数还有其他的用法,例如可以指定行分隔符为其他字符或字符串,并且可以从文件或其他输入流中读取数据。根据具体用法,函数的语法和参数可能会有所不同。

指定行分隔符:

默认情况下,getline 函数的行分隔符为换行符 \n。如果需要指定其他的行分隔符,可以使用第三个参数 delim。例如,下面的代码将从标准输入流中读取一行数据,以逗号为行分隔符:

string input;
getline(cin, input, ',');

在这个例子中,cin 是标准输入流对象,input 是存储读取数据的字符串对象,',' 是指定的行分隔符。函数 getline(cin, input, ',') 从标准输入流对象 cin 中读取一行数据,以逗号为行分隔符,存储到字符串变量 input 中。

stringstream ss(data);
string item;
queue<string> q;
while (getline(ss, item, ',')) 
    q.push(item);

这段代码将一个以逗号分隔的字符串 data 中的每个元素,逐个压入一个队列中。具体来说,它使用了 stringstreamgetline 函数来实现字符串分割,以逗号为分隔符,将每个子字符串作为队列的元素。

具体来说,首先创建了一个 stringstream 对象 ss,将待分割的字符串 data 作为参数传入。接着,定义一个字符串变量 item,用于存储每个子字符串。然后,创建一个队列 q,用于存储分割后的每个子字符串。在 while 循环中,使用 getline 函数逐行读取 ss 中的数据,以逗号作为分隔符,将每个子字符串存储到 item 变量中,然后将 item 插入到队列 q 的末尾。最终,当所有子字符串都被读取和插入到队列 q 后,队列中存储的就是分割后的每个子字符串了。

这段代码可以用于解析一些逗号分隔的数据格式,例如 CSV 文件或一些自定义的数据格式,例如上面提到的二叉树序列化格式。通过将输入的字符串分割成一个个子字符串,并逐个处理,可以更方便地对这些数据进行处理和解析。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值