二叉树的建立、遍历,以及给定二叉树前序遍历和中序遍历重建二叉树问题。
2015-01-05 08:42
441 查看
开始的时候不大理解头结点的意义,所以二叉树的建立部分现在看来写的不够满意。尤其是定义常量N、并预先分配node
,先贴上来一会改成new分配新的空间的形式。
以下是二叉树建立的代码部分,放在一个头文件tree.h中(开头的宏定义不是很会用):
/*————————————————————————————————————————————————————————————*/
接下来的问题是重建二叉树。
将函数命名为DivideAndFind_Tree()是因为希望在函数中实现三个功能:
1.寻找到下一个根节点在中序遍历中的位置,分配一块内存来存放它,并且把该内存的tree.data赋值为‘下一个根节点’的值
2.确认下一个根节点是左子树还是右子树(通过角标来判断),然后把指针指向它
3.以这个位置为界,`划分左右树的区域,作为新的top end去递归 ;
在递归的过程中唯一要注意的就是递归前的判断条件,什么时候return是成功运行的重点。这里有几个return的条件,但是据观测都是top>end条件return的,其它两个条件并没有出现
以下为代码部分,放在rebuild_pro.h头文件中。
/*————————————————————————————————————————————————————————————*/
下面是main函数部分,可以知道最后运行结果是正确的。开始的宏定义该怎么用还有待了解……
到此主要内容完毕,下面有一些不太重要的补充内容。
/*—————————————————————————————————————————————————————*/
在自己写的版本中有一个带输出的rebuild,把输出结果贴上来,也有助于了解二叉树重建中递归的具体细节吧!
(看看那么多注释……当时思路不清晰,现在写完之后理解的就透彻多了)
,先贴上来一会改成new分配新的空间的形式。
以下是二叉树建立的代码部分,放在一个头文件tree.h中(开头的宏定义不是很会用):
#ifndef _IOSTREAM_ #define _IOSTREAM_ #include<iostream> #endif using namespace std; const int N=16; struct tree { int data; tree *left; tree *right; }node ;//注意这里node 是无序的,只是为了方便建立了一个,也可以用new的。 void CreateTree(tree &root,int value) { root.data=value; root.left=root.right=NULL; } void AddTree(tree &root,tree &leaf,bool choose,int value)//bool 0代表左子树,1代表右子树 { if(value==0) { (choose?root.right:root.left)=NULL; return; } (choose?root.right:root.left)=&leaf; leaf.data=value; leaf.left=leaf.right=NULL; }遍历部分:
void VisitTree_1(tree &T)//可以调整前序遍历、中序遍历、后序遍历 //算法复杂度为O(n),递归工作栈的深恰好为树的高度。 { if(&T!=NULL)//我不加else设置为NULL竟然还可以正常判断? { cout<<T.data<<'/'; VisitTree_1(*T.left); VisitTree_1(*T.right); } } void VisitTree_2(tree &T) { if(&T!=NULL) { VisitTree_2(*T.left); cout<<T.data<<'/'; VisitTree_2(*T.right); } } void VisitTree_3(tree *T) { if(T!=NULL) { VisitTree_3(T->left); VisitTree_3(T->right); cout<<T->data<<'/'; } }为了方便使用,可选函数AddTreeFromArray(),功能是从一个数组(不满的节点值写成0)建立二叉树
void AddTreeFromArray(int a[]) { int used=0,i=0; bool choose=0; //tree * queue ;//想用队列来实现,不过对于完全二叉树,他是有规律的这一步先不写 CreateTree(node[0],a[used++]); while(used<N-1)//我原本想在行16修改了边界条件,不过内存中未必是一个负值,还是考虑-1吧 { AddTree(node[i],node[i*2+1],0,a[used++]); AddTree(node[i],node[i*2+2],1,a[used++]); i++; } }以上即可实现一个二叉树建立的过程,整体比较简单,需要注意的是在创建新节点时记得把左右指针设置为NULL,否则会出问题。
/*————————————————————————————————————————————————————————————*/
接下来的问题是重建二叉树。
将函数命名为DivideAndFind_Tree()是因为希望在函数中实现三个功能:
1.寻找到下一个根节点在中序遍历中的位置,分配一块内存来存放它,并且把该内存的tree.data赋值为‘下一个根节点’的值
2.确认下一个根节点是左子树还是右子树(通过角标来判断),然后把指针指向它
3.以这个位置为界,`划分左右树的区域,作为新的top end去递归 ;
在递归的过程中唯一要注意的就是递归前的判断条件,什么时候return是成功运行的重点。这里有几个return的条件,但是据观测都是top>end条件return的,其它两个条件并没有出现
以下为代码部分,放在rebuild_pro.h头文件中。
/*————————————————————————————————————————————————————————————*/
#ifndef _TREE_H_ #define _TREE_H_ #include<iostream> #include "tree.h" #endif #include<stdio.h> const int M=5; int a[M]={1,2,4,5,3}; int b[M]={4,2,5,1,3}; int *queue=a; //类似队列一样的变量,用来记录哪个值还未查询过。因为递归的问题不能在a[]中查找根节点值然后角标+1来作为下一个根节点值 tree* createnode_dynamic() { tree *p=new tree; p->left=p->right=NULL; return p; }//分配好新建立的内存的左右指针值,错误就迎刃而解了! int FindValueInA(int array[],int find) { for(int i=0;i<M;i++) if(array[i]==find) return i; return -1; } void DivideAndFind_Tree(tree *root,int top,int end) { if(top>end) return; int root_in_a=FindValueInA(a,root->data); //如果不在a[]中返回值为-1,代表他是头结点,其右子树即为重建后的结果。 int root_in_b=FindValueInA(b,root->data); if(root_in_a+1>=5)//数组超了,代表没有下一个了也就是查找完毕 { //printf("return because next root do not exsist:\n"); return; } int next_root_value=*queue;//int cut = find next root in top-end; int next_root_in_b=FindValueInA(b,next_root_value); tree* p=createnode_dynamic();//create a new memory if(next_root_in_b<root_in_b)//这句话使得所有的非头结点都在右侧了.如果更改FindValueInA的返回值为M可以变成左子树 { root->left=p; root->left->data=next_root_value; queue++; }//if root.value in right, root->left=p; else if(next_root_in_b>root_in_b) { root->right=p; root->right->data=next_root_value; queue++; }//if root.value in left, root.right=p; else //if equal....I don't know return; DivideAndFind_Tree(p,top,next_root_in_b-1); DivideAndFind_Tree(p,next_root_in_b+1,end); }以上即为重建二叉树的过程,为了方便直接设置了一个前序遍历a[M]、中序遍历b[M]。主要还是想验证重建过程的正确
下面是main函数部分,可以知道最后运行结果是正确的。开始的宏定义该怎么用还有待了解……
#include<iostream> #ifndef _TREE_H_ #define _TREE_H_ #include "tree.h" #endif // !_TREE_H_ #ifndef _REBUILD_PRO_H_ #define _REBUILD_PRO_H_ #include "rebuild.h" #endif // !_REBUILD_H_ using namespace std; int main() { tree* head=createnode(); head->data=-1; DivideAndFind_Tree(head,0,M-1); cout<<"前序遍历:"; VisitTree_1(*head->right); cout<<"\n中序遍历:"; VisitTree_2(*head->right); cout<<"\n后序遍历:"; VisitTree_3(head->right); getchar(); return 0; }
到此主要内容完毕,下面有一些不太重要的补充内容。
/*—————————————————————————————————————————————————————*/
在自己写的版本中有一个带输出的rebuild,把输出结果贴上来,也有助于了解二叉树重建中递归的具体细节吧!
(看看那么多注释……当时思路不清晰,现在写完之后理解的就透彻多了)
void DivideAndFind_Tree(tree *root,int top,int end) { cout<<"Divide in "<<top<<" to "<<end<<" root's value is :"<<root->data<<'\n'; if(top>end) { printf("return because top>end\n"); return; } /*if(root->data<0) { //root->data=*queue++; return; }*/ int root_in_a=FindValueInA(a,root->data); //如果不在a[]中代表他是头结点,那么把它下一个节点设为a[0] int root_in_b=FindValueInA(b,root->data); //这句没用了。if(root_in_b==-1); if(root_in_a+1>=5)//数组超了,代表没有下一个了也就是查找完毕 { printf("return because next root do not exsist:\n"); return; } int next_root_value=*queue;//int cut = find next root in top-end; int next_root_in_b=FindValueInA(b,next_root_value); tree* p=createnode_dynamic();//create a new memory if(next_root_in_b<root_in_b)//这句话使得所有的非头结点都在右侧了! { root->left=p; root->left->data=next_root_value; queue++; cout<<"I create ["<<next_root_value<<"] in left, father is:["<<root->data<<"]\n"; }//if root.value in right, root->left=p; else if(next_root_in_b>root_in_b) { root->right=p; root->right->data=next_root_value; queue++; cout<<"I create :["<<next_root_value<<"[in right, father is:["<<root->data<<"]\n"; }//if root.value in left, root.right=p; else //if equal....I don't know { printf("return because next root = now root\n"); return; } printf("next root's (%d) place in b is %d\n",next_root_value,next_root_in_b); printf("will divide %d -- %d && %d -- %d \n",top,next_root_in_b-1,next_root_in_b+1,end); DivideAndFind_Tree(p,top,next_root_in_b-1); DivideAndFind_Tree(p,next_root_in_b+1,end); } //初始节点划分域 错误!在其中加入两个递归.加递归不行。现在主函数中划分一次吧.理想方案是加头结点..竟然去掉那句就对了……………… //原值要用队列,不然递归回去会找错人 //都找完了,找不到next value,无意义循环输出结果:
相关文章推荐
- 二叉树的建立以及先序、中序、后序遍历C语言实现
- 二叉树建立以及先序、中序、后序、层次遍历(JAVA 实现)
- 根据二叉树前序遍历和中序遍历的结果,重建出该二叉树并后序遍历之 java代码
- 二叉树的建立以及前序、中序、后序遍历的递归和非递归实现
- 通过前序遍历和中序遍历重建二叉树以及输出后序遍历(Java实现)(二)
- 通过前序遍历和中序遍历重建二叉树以及输出后序遍历(Java实现)
- 二叉树的建树,按层遍历,结点总数,页结点,深度以及三序非递归遍历二叉树,建立中序线索二叉树
- Binary Tree——给定二叉树的前序遍历和中序遍历重建二叉树
- 二叉树的建立以及先序,中序,后序遍历
- 已知二叉树前序遍历和中序遍历的结果,重建二叉树
- python实现二叉树的建立以及遍历(递归前序、中序、后序遍历,队栈前序、中序、后序、层次遍历)
- 根据前序和中序遍历的结果建立二叉树
- 二叉树的创建以及利用迭代实现中序、先序、后序遍历、清空
- 二叉树建立、遍历(前序,中序,后序),求叶节点个数,求节点个数
- 二叉树的建立和中序、先序、后序遍历
- 二叉树先序后序递归建立,前中后序层次非递归遍历,以及统计叶子结点个数以及树的深度
- 给定先序:ABCDEFGHIJK 给定中序:CBEDGFAHJIK 首先分析上述给定的先,中序,首先得知先序遍历的肯定是二叉树的根节点:A,在看中序遍历,根据中序遍历的原理可知,在A左边的一定全部属于
- 二叉树(二叉排序树)的建立以及遍历
- 扩展二叉树 建立 以及 前序遍历 中序遍历 后序遍历 的非递归算法
- 二叉树的先序以及后序递归建立,先中后序递归遍历。