目前正準備2020屆秋招 算法工程師,複習數據結構!ios
發現樹遍歷能夠達到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<<"\nRecursive results:"<<endl; inorder(root); return 0; }