二叉树的一些操作:先序、中序、后序遍历的非递归实现,层序遍历,树的深度,第K层的节点数,最小公共祖先节点,由先序序列和中序序列还原二叉树。
C++实现,简单起见,没用模板。递归算法比较直观,此处从略,故给出大多是非递归算法。
struct TreeNode
{
int key;
TreeNode *lchild;
TreeNode *rchild;
TreeNode *pre;
TreeNode *post;
};
void visit(TreeNode *node)
{
if(node)
{
cout<<node->key<<" ";
}
}
//非递归的先序遍历
void pre_travel(TreeNode *root)
{
if(!root)
return;
stack<TreeNode*> s;
TreeNode *p=root;
s.push(root);
while(!s.empty())
{
p = s.top();
visit(p);
s.pop();
if(p->rchild)
s.push(p->rchild);
if(p->lchild)
s.push(p->lchild);
}
}
//非递归的中序遍历
void in_travel(TreeNode *root)
{
stack<TreeNode*> s;
s.push(root);
TreeNode *p = root;
while(!s.empty())
{
while((p = s.top()))
s.push(p->lchild);
s.pop();
if(!s.empty())
{
p = s.top();
visit(p);
s.pop();
s.push(p->rchild);
}
}
}
//非递归的后序遍历
void post_travel(TreeNode *root)
{
stack<TreeNode*> s;
stack<bool> s2;
TreeNode *p=root;
s.push(p);
s2.push(false);
while(!s.empty())
{
if((p=s.top()))
{
if(s2.top() || (!p->lchild && !p->rchild))
{
visit(p);
s.pop();
s2.pop();
}else
{
s2.pop();
s2.push(true);
if(p->rchild)
{
s.push(p->rchild);
s2.push(false);
}
if(p->lchild)
{
s.push(p->lchild);
s2.push(false);
}
}
}else
s.pop();
}
}
//层序遍历
void level_travel(TreeNode *root)
{
if(!root)
return;
queue<TreeNode*> q;
TreeNode *p=root;
q.push(root);
while(!q.empty())
{
p = q.front();
visit(p);
q.pop();
if(p->lchild)
q.push(p->lchild);
if(p->rchild)
q.push(p->rchild);
}
}
//树的层数
int get_levels(TreeNode *root)
{
int count = 0;
queue<TreeNode*> q;
TreeNode *p = root;
TreeNode *start = root;
q.push(root);
while(!q.empty())
{
if((p=q.front()))
{
if(start && p==start)
{
++count;
if(p->lchild)
start = p->lchild;
else
start = p->rchild;
}
q.pop();
if(p->lchild)
{
q.push(p->lchild);
if(!start)
start = p->lchild;
}
if(p->rchild)
{
q.push(p->rchild);
if(!start)
start = p->rchild;
}
}
}
return count;
}
int get_levels_recusion(TreeNode *root)
{
if(!root)
return 0;
return (max(get_levels_recusion(root->lchild),get_levels_recusion(root->rchild))+1);
}
//第k层的节点数
int get_node_count(TreeNode *root,int k)
{
if(!root || k<=0)
return 0;
queue<TreeNode*> q;
TreeNode *p,*start = root;
int count = 0;
int level = 0;
q.push(root);
while(!q.empty())
{
if((p=q.front()) == start)
{
if(level == k)
return count;
++level;
count = 0;
if(p->lchild)
start = p->lchild;
else
start = p->rchild;
}
++count;
q.pop();
if(p->lchild)
{
q.push(p->lchild);
if(!start)
start = p->lchild;
}
if(p->rchild)
{
q.push(p->rchild);
if(!start)
start = p->rchild;
}
}
if(k == level)
return count;
return 0;
}
//两节点的最小公共祖先
TreeNode* lcp(int key1,int key2,TreeNode *root)
{
if(!root)
return 0;
stack<int> f;//取值0,1,2.1表示已插入左孩子;2表示已插入右孩子。
stack<TreeNode*> s1;
stack<TreeNode*> s2;
bool find1 = false;
bool find2 = false;
TreeNode *p=root;
s1.push(p);
s2.push(p);
f.push(0);
while((!find1 && !s1.empty()) || (!find2 && !s2.empty()))
{
if(!find1)
p = s1.top();
else
p = s2.top();
if(f.top() == 0)//第一次访问该节点
{
if(!find1 && p->key == key1)
find1 = true;
if(!find2 && p->key == key2)
find2 = true;
if(find1 && find2)
break;
f.pop();
f.push(1);
if(p->lchild)
{
if(!find1)
s1.push(p->lchild);
if(!find2)
s2.push(p->lchild);
f.push(0);
}
}
if(f.top() == 1)//已访问过该节点和左子树
{
f.pop();
f.push(2);
if(p->rchild)
{
if(!find1)
s1.push(p->rchild);
if(!find2)
s2.push(p->rchild);
f.push(0);
}
}
if(f.top() == 2)//以访问过该节点和左右子树
{
f.pop();
if(!find1)
s1.pop();
if(!find2)
s2.pop();
}
}
if(find1 && find2)
{
while(s1.size()!=s2.size())
if(s1.size()>s2.size())
s1.pop();
else
s2.pop();
while(s1.top() != s2.top())
{
s1.pop();
s2.pop();
}
return s1.top();
}
return 0;
}
//由先序遍历序列和中序遍历序列还原树
TreeNode* pre_in_tree(const string& pre,const string& in,bool &flag)
{
if(pre.length() != in.length() || pre.length() == 0)
return 0;
TreeNode *root = new TreeNode;
int index = in.find_first_of(pre[0]);
if(index == -1)
{
flag = false;
return 0;
}
root->key = pre[0]-'0';
root->lchild = pre_in_tree(pre.substr(1,index),in.substr(0,index),flag);
root->rchild = pre_in_tree(pre.substr(index+1),in.substr(index+1),flag);
if(flag)
return root;
else
return 0;
}
//转置
TreeNode* transpose(TreeNode *root)
{
if(root == NULL)
return NULL;
stack<TreeNode*> s1;
stack<bool> s2;
TreeNode *p = root;
s1.push(root);
s2.push(false);
while(!s1.empty())
{
p = s1.top();
if(!s2.top())
{
s2.pop();
s2.push(true);
if(p->rchild)
{
s1.push(p->rchild);
s2.push(false);
}
if(p->lchild)
{
s1.push(p->lchild);
s2.push(false);
}
}else
{
TreeNode *q = p->lchild;
p->lchild = p->rchild;
p->rchild = q;
s1.pop();
}
}
return p;
}