二叉树的遍历是指按照一定次序访问二叉树中的所有节点,且每个节点仅被访问一次的过程。是最基本的运算,是其他运算的基础。
二叉树有两种存储结构:顺序存储和链式存储
顺序存储: (对完全二叉树来说,可以充分利用存储空间,但对于一般的二叉树,只有少数的存储单元被利用)
[cpp]
view plain
copy
- typedef struct
- {
- ElemType data[MaxSize];
- int n;
- }SqBTree;
链式存储:
[csharp]
view plain
copy
- typedef struct node
- {
- ElemType data;
- struct node *lchild;
- struct node *rchild;
- } BTNode;
二叉树三种递归的遍历方法:
先序遍历 | 访问根节点→先序遍历左子树→先序遍历右子树 |
中序遍历 | 中序遍历左子树→访问根节点→中序遍历右子树 |
后序遍历 | 后序遍历左子树→后序遍历右子树→访问根节点 |
二叉树遍历的递归算法:
[cpp]
view plain
copy
- void preOrder(BTNode *b) //先序遍历递归算法
- {
- if (b!=NULL)
- {
- visit(b);
- preOrder(b->lchild);
- preOrder(b->rchild);
- }
- }
- void InOrder(BTNode *b) //中序遍历递归算法
- {
- if(b!=NULL)
- {
- InOrder(b->lchild);
- visit(b);
- InOrder(b->rchild);
- }
- }
- void PostOrder(BTNode *b) //后序遍历递归算法
- {
- if(b!=NULL){
- PostOrder(b->lchild);
- PostOrder(b->rchild);
- visit(b);
- }
- }
二叉树非递归遍历算法:
有两种方法:①用栈存储信息的方法 ②增加指向父节点的指针的方法 暂时只介绍下栈的方法
先序遍历:
[cpp]
view plain
copy
- void PreOrder(BTNode *b)
- {
- Stack s;
- while(b!=NULL||!s.empty())
- {
- if(b!=NULL){
- visit(b);
- s.push(b);
- b=b->left;
- }
- else{
- b=s.pop();
- b=b->right;
- }
- }
- }
中序遍历:
[cpp]
view plain
copy
- void InOrder(BTNode *b){
- Stack s;
- while(b!=NULL||!s.empty()){
- if (b!=NULL)
- {
- s.push(b);
- s=s->left
- }
- if(!s.empty()){
- b=s.pop();
- visit(b);
- b=b->right;
- }
- }
- }
后序遍历:
[cpp]
view plain
copy
- void PostOrder(BTNode *b){
- Stack s;
- while(b!=NULL){
- s.push(b);
- }
- while(!s.empty()){
- BTNode* node=s.pop();
- if(node->bPushed){
- visit(node);
- }
- else{
- s.push(node);
- if(node->right!=NULL){
- node->right->bPushed=false;
- s.push(node->right);
- }
- if(node->left!=NULL){
- node->left->bpushed=false;
- s.push(node->left);
- }
- node->bPushed=true; //如果标识位为true,则表示入栈
- }
- }
- }
层次遍历算法:(用队列的方法)
[cpp]
view plain
copy
- void levelOrder(BTNode *b){
- Queue Q;
- Q.push(b);
- while(!Q.empty()){
- node=Q.front();
- visit(node);
- if(NULL!=node->left){
- Q.push(node->left);
- }
- if(NULL!=right){
- Q.push(node->right);
- }
- }
- }<span style=“”></span>
已知先序和中序求后序的算法:(已知后序和中序求先序的算法类似,但已知先序和后序无法求出中序)
[cpp]
view plain
copy
- int find(char c,char A[],int s,int e) /* 找出中序中根的位置。 */
- {
- int i;
- for(i=s;i<=e;i++)
- if(A[i]==c) return i;
- }
- /* 其中pre[]表示先序序,pre_s为先序的起始位置,pre_e为先序的终止位置。 */
- /* 其中in[]表示中序,in_s为中序的起始位置,in_e为中序的终止位置。 */
- /* pronum()求出pre[pre_s~pre_e]、in[in_s~in_e]构成的后序序列。 */
- void pronum(char pre[],int pre_s,int pre_e,char in[],int in_s,int in_e)
- {
- char c;
- int k;
- if(in_s>in_e) return ; /* 非法子树,完成。 */
- if(in_s==in_e){printf(“%c”,in[in_s]); /* 子树子仅为一个节点时直接输出并完成。 */
- return ;
- }
- c=pre[pre_s]; /* c储存根节点。 */
- k=find(c,in,in_s,in_e); /* 在中序中找出根节点的位置。 */
- pronum(pre,pre_s+1,pre_s+k-in_s,in,in_s,k-1); /* 递归求解分割的左子树。 */
- pronum(pre,pre_s+k-in_s+1,pre_e,in,k+1,in_e); /* 递归求解分割的右子树。 */
- printf(“%c”,c); /* 根节点输出。 */
- }
- main()
- {
- char pre[]=“abdc”;
- char in[]=“bdac”;
- printf(“The result:”);
- pronum(pre,0,strlen(in)-1,in,0,strlen(pre)-1);
- getch();