目前正准备2020届秋招 算法工程师,复习数据结构!
发现树遍历可以达到O(n)时间复杂度,O(1)空间复杂度(Morris遍历),赶紧学习了一波。并复习了建立树、遍历树的一些基本操作。
#include<iostream> #include<queue> #include<cstring> using namespace std; struct TreeNode{ int val; TreeNode *left, *right; TreeNode(int x): val(x), left(NULL), right(NULL){} }; //初始化树 TreeNode* init_tree1(TreeNode *root, int val){ if(root==NULL){ root = new TreeNode(val); return root; } if(val<root->val){ root->left = create_tree(root->left, val); }else{ root->right = create_tree(root->right, val); } return root; } //初始化树 void init_tree2(TreeNode *&root){ string data; cin>>data; if(data=="#"){ root=NULL; }else{ root = new TreeNode(stoi(data)); init_tree(root->left); init_tree(root->right); } } //中序遍历,时间复杂度O(n),空间复杂度O(1) void MorrisTraversal(TreeNode *root){ TreeNode *cur = root, *prev = NULL; while(cur!=NULL){ //1. 如果该节点左子树为空,则输出 if(cur->left==NULL){ cout<<cur->val<<" "; cur = cur->right; //指向父亲节点 }else{ prev = cur->left; while(prev->right!=NULL && prev->right!=cur){ prev = prev->right; //找当前节点左子树最右的节点 } if(prev->right==NULL){ prev->right = cur; cur = cur->left; }else if(prev->right==cur){ //说明该节点直接前驱已访问,则访问该节点 cout<<cur->val<<" "; //下一步指向该节点右子树,继续进行 cur = cur->right; prev->right = NULL; //恢复为原来节点结构 } } } cout<<endl; } //中序遍历,时间复杂度O(n),空间复杂度O(n) void inorder(TreeNode *root){ if(root){ inorder(root->left); cout<<root->val<<" "; inorder(root->right); } } //层次遍历 void levelOrder(TreeNode* root){ queue<TreeNode*> q; q.push(root); while(!q.empty()){ int size = q.size(); for(int i=0;i<size;i++){ TreeNode *temp = q.front(); q.pop(); cout<<temp->val<<" "; if(temp->left) q.push(temp->left); if(temp->right) q.push(temp->right); } cout<<endl; } } int main(){ TreeNode *root=NULL; int s[] = {4,2,6,1,3,5}; for(int i=0;i<6;i++) root = init_tree1(root, s[i]); //init_tree2(root); levelOrder(root); cout<<"Morris results: "<<endl; MorrisTraversal(root); cout<<" Recursive results:"<<endl; inorder(root); return 0; }