二叉树,可以用指针来存也可以用数组来存,使用数组的时候应该是完全二叉树。
在数组存储的方式中(认为根节点是1),当前节点是x,左子孩子是2*x,到第n层有2^n-1个节点。要判断为空,就是下标大于节点总个数,判断有无子树就用2*x和n判断。
在指针存储的时候,记得初始化root为node*root=NULL,所有的新节点左右子树都是NULL
root=NULL,root->lchild=NULL,root->rchild=NULL,代表的是他们没有指向。
定义的时候是指针,在修改其指向的内容的时候正常修改就行(一直指向A,A里面元素被改了),如果修改其内容(就是修改指针指向的对象,由指向A变成指向B)要使用引用
里面的change(node*&root),要这种格式,别忘了还是指针,要有*,在调用的时候直接change(root)就可以。
#include<stdio.h> struct node{ int data; node*lchild; node*rchild; }; node*root=NULL;//建树之前不存在,初始为空 node*newNode(int v) { node*Node=new node; Node->data=v; Node->lchild=NULL; Node->rchild=NULL; return Node; }//新建节点 void search(node*root,int x,int newdata) { if(root==NULL) return ; if(root->data==x) root->data=newdata; search(root->lchild,x,newdata); search(root->rchild,x,newdata); } void insert(node*&root,int x) { if(root==NULL) { root=newNode(x); return; } if(root->data==1)//什么条件在左子树插入 insert(root->lchild,x); else insert(root->rchild,x); } node*Create(int data[],int n) { node*root=NULL; for(int i=0;i<n;i++) insert(root,data[i]); return root; }
指针中几个常用的操作代码如上。
先中后序还有层次遍历递归实现代码如下
#include<stdio.h> #include<queue> using namespace std; struct node{ int data; node*lchild; node*rchild; }; node*newNode(int v) { node*Node=new node; Node->data=v; Node->lchild=NULL; Node->rchild=NULL; return Node; } void preOrder(node*root) { if(root==NULL) return; printf("%d",root->data); preOrder(root->lchild); preOrder(root->rchild); } void inOrder(node*root) { if(root==NULL) return; inOrder(root->lchild); printf("%d",root->data); inOrder(root->rchild); } void postOrder(node*root) { if(root==NULL) return; postOrder(root->lchild); postOrder(root->rchild); printf("%d",root->data); } void LayerOrder(node*root) { queue<node*>q; q.push(root); node*temp=q.front(); while(!q.empty()) { node*temp=q.front(); q.pop(); if(temp->lchild!=NULL) q.push(temp->lchild); if(temp->rchild!=NULL) q.push(temp->rchild); printf("%d",temp->data); } } int main() { node *root=newNode(1); root->lchild=newNode(2); root->rchild=newNode(3); root->lchild->lchild=newNode(4); root->lchild->rchild=newNode(5); root->rchild->rchild=newNode(6); preOrder(root); printf("\n"); inOrder(root); printf("\n"); postOrder(root); printf("\n"); LayerOrder(root); printf("\n"); return 0; }
注意,给定中序遍历和先后层次中任意一个,可以确定二叉树,给后面中的两个是不能确定的。中序用于确定左右子树,后面三个任一个都可以确定根节点。
这里面的生成条件,需要子树里面的data没有重复的元素。
PAT A1020给定后序中序生成二叉树,并以层次遍历输出
这个需要注意,要求结尾没有多余空格,加个判断就行。
具体思路就是,每次最尾的是根节点,根节点在中序中判断左右子树以后,求出左右子树的节点数目,再划分出后序里面哪些属于左右,前转中同理。
#include<stdio.h> #include<iostream> #include<queue> using namespace std; int n; int in[35]; int post[35]; struct node { int data; node*lchild; node*rchild; }; void level(node*root) { queue<node*>q; q.push(root); while(!q.empty()) { node*temp=q.front(); q.pop(); if(temp->lchild!=NULL) q.push(temp->lchild); if(temp->rchild!=NULL) q.push(temp->rchild); if(!q.empty()) printf("%d ",temp->data); else printf("%d",temp->data); } } node* change(int inl1,int inr1,int post1,int post2) { if(inl1>inr1) return NULL; node*root=new node; root->data=post[post2]; //printf("here:%d\n",root->data); int temp=-1; for(int i=inl1;i<=inr1;i++) { if(in[i]==post[post2]) { temp=i; break; } } if(temp!=-1) { root->lchild=change(inl1,temp-1,post1,post1+temp-inl1-1); root->rchild=change(temp+1,inr1,post1+temp-inl1,post2-1); } return root; } int main() { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&post[i]); for(int i=0;i<n;i++) scanf("%d",&in[i]); level(change(0,n-1,0,n-1)); return 0; }
如果题目考察层次遍历和中序,那么是选中根节点,划分左右子树以后,使用vector,然后判断中序中左右出现的节点和层次中相同,(根据其在层次遍历中的顺序)加入左或者右对应的数组,再进行下一轮递归。