做leetcode的过程中总是遇到树的这些操作,特此总结一下,便于以后查看。
其中层次遍历属于广度优先搜索,其他属于深度优先搜索。
我之前数据结构零基础,因此,在过程中算法可能不够完美,请各位留言指正。另外,会借鉴别的算法,用来比较学习,如果有侵权,请联系博主~
这里用类似leetcode的命名规则。
树结构声明:
struct treeNode
{
int val;
treeNode *left;
treeNode *right;
};
创建一棵树:
void CreateTree(treeNode *&root)
{
std::cout << "请输入:" << " " << std::endl;
int x;
std::cin >> x;
if (x == 110)
root = NULL;
else
{
root = new treeNode;
root->val = x;
CreateTree(root->left);
CreateTree(root->right);
}
}
层次遍历一(广度优先搜索):
将每一层放进层节点vector,然后遍历vector,打印节点值;然后将vector中下一层的所有节点放入另一个临时vector,将临时vector中的内容赋给层节点vector。
vector<vector<int>> levelOrder(treeNode* root) {
if(!root)
return {};
vector<vector<int>> result;
vector<TreeNode*> levelNode;
levelNode.push_back(root);
while(!levelNode.empty())
{
vector<treeNode*> temp;
vector<int> levelval;
for(int i = 0;i < levelNode.size(); i++)
{
levelval.push_back(levelNode[i]->val);
if(levelNode[i]->left)
temp.push_back(levelNode[i]->left);
if(levelNode[i]->right)
temp.push_back(levelNode[i]->right);
}
result.push_back(levelval);
levelNode.swap(temp);
}
reverse(result.begin(),result.end());
return result;
}
有些人用queue做的,原理一样,queue先进先出,只需要将vector为空的条件改为弹出次数为本层压入节点数就可以将层分开,也可以用特殊的分隔符。
vector<vector<int>> levelOrder(treeNode* root) {
if(!root)
return {};
vector<vector<int>> result;
vector<TreeNode*> levelNode;
levelNode.push_back(root);
while(!levelNode.empty())
{
vector<treeNode*> temp;
vector<int> levelval;
for(int i = 0;i < levelNode.size(); i++)
{
levelval.push_back(levelNode[i]->val);
if(levelNode[i]->left)
temp.push_back(levelNode[i]->left);
if(levelNode[i]->right)
temp.push_back(levelNode[i]->right);
}
result.push_back(levelval);
levelNode.swap(temp);
}
reverse(result.begin(),result.end());
return result;
}
层次遍历二:
用数字标记层次,第一层用0,依次加一,然后将相同字数标记为一层
vector<vector<int>> levelOrder(treeNode* root) {
if(!root)
return {};
vector<vector<int>> result;
vector<TreeNode*> levelNode;
levelNode.push_back(root);
while(!levelNode.empty())
{
vector<treeNode*> temp;
vector<int> levelval;
for(int i = 0;i < levelNode.size(); i++)
{
levelval.push_back(levelNode[i]->val);
if(levelNode[i]->left)
temp.push_back(levelNode[i]->left);
if(levelNode[i]->right)
temp.push_back(levelNode[i]->right);
}
result.push_back(levelval);
levelNode.swap(temp);
}
reverse(result.begin(),result.end());
return result;
}
先序遍历:
先序遍历顺序是根->左->右,每一个孩子节点都可以当做根来处理。
void preorder(treeNode* root)
{
if (!root)
return;
cout<<root->val<<" ";
preorder(root->left);
preorder(root->right);
}
中序遍历:
中序遍历的顺序是左->根->右
void miorder(treeNode* root)
{
if (!root)
return;
miorder(root->left);
cout<<root->val<<" ";
miorder(root->right);
}
后序遍历:
后序遍历顺序是左->右->根,可以看出是先序的反序,如果将先序所有left和right调换,则顺序是根->右->左,再逆序就是左->右->根。
vector<int> res;
void postorder(treeNode* root)
{
if (!root)
return;
res.push_back(root->val);
postorder(root->right);
postorder(root->left);
}
reverse(res.begin(),res.end());
这些都是用递归实现的,也可以用迭代实现,迭代要用stack,迭代的效率比递归要低,用过一次结果超时,所以就没再用过,在这里也就不班门弄斧~
声明:本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。