双向线索二叉树的正反遍历(C语言)

#include<stdio.h>
#include<stdlib.h>

//定义结构体
typedef struct node{
        char data;
        struct node *left, *right;
        int Lflag;
	int Rflag; //左右标志是左右子树还是前驱后继节点, 1: 左右子树,,0;前驱后继节点
}Node,*TreeNode;

TreeNode pre = NULL;

//利用前序创建树,若使用中序或者后序,只需调正一下语句位置
void createTree(TreeNode *T){
    	
        char data;
	scanf("%c",&data);
        if(T!=NULL){
                if(data != '#'){
                        //分配内存
                        if(!((*T) = (Node *)malloc(sizeof(Node)))){
                                printf("申请内存失败!");
                                return;
                        }//赋值
                        else{
			   (*T) ->data = data;
                           createTree(&((*T)->left));  //初始化左子树
                           createTree(&((*T)->right));
						}
                }else{
                        (*T) = NULL;
                }
			}
		
        
}
//中序遍历
void mid_SearchTest(TreeNode T){
        if(T){
                mid_SearchTest(T->left);
                printf("%c ", T->data);
                mid_SearchTest(T->right);
        }
}

//中序对二叉树进行线索化
void mid_InThreading(TreeNode T){
        if(T){
                mid_InThreading(T ->left);  //递归左子树线索化
                //如果当前节点没有左孩子,则左标志设为1,指向上一个节点pre
                if(!(T->left)){
                        T ->Lflag = 1;
                        T ->left = pre;
                }
                //如果pre没有右节点,则右标志为1,指向下一个节点
                if(pre != NULL && pre ->right ==NULL){
                        pre ->Rflag = 1;
						//back the father
                        pre ->right = T;
                }
                pre = T;  //pre 指向当前节点
                mid_InThreading(T ->right);  //递归右子树
        }
}



//中序遍历线索二叉树

void mid_Search(TreeNode T){
        while(T){
                //一直找左子树,最后一个左节点输出
			   
                while(T ->Lflag != 1){
                        T = T ->left;
                }

                printf("%c ",T->data);
		

                //当节点右标志为1时,直接找到其后继节点
                while(T->Rflag == 1 && T ->right != NULL){
                        T = T->right;
                        printf("%c ",(T ->data));
						
                }

                //否则,找到其右子树的最下边的左节点遍历
                T =T->right;
        }
        
}
//双向线索二叉树,增加一个头节点,头节点的左节点指向根节点,右节点指向最后一个节点(pre:为全局变量,最后指向最后一个节点)
void doubleReaction_Thread(TreeNode *H,TreeNode T){
        //为头节点申请内存
	    *H = (TreeNode)malloc(sizeof(Node));
       if((*H) == NULL){
			printf("申请内存失败!");
			return;
	   }

		   (*H) ->right = *H;
		   (*H) ->Rflag = 0;

		   //若树为空
		   if(T == NULL){
			  (*H) ->left = *H;
			  (*H) ->Lflag = 0;
		   }
		   else{
				   pre = *H;  //将pre指向头节点
				   (*H) ->left = T;  //头节点·的左节点指向根节点
				   (*H) ->Lflag = 1;

				   mid_InThreading(T); //结束后,pre指向最后一个节点
				   //将头节点接在最后一个节点的后面
				   pre ->right = *H;
				   pre ->Rflag = 1;
				   (*H)->right = pre;
		   }
	   
}

//中序正向遍历
void zheng_Search(TreeNode H){
        TreeNode p;
        p = H->left;
        mid_Search(p);
}

//中序逆向
void  ni_Search(TreeNode H){
        TreeNode p;
        p = H->right;
        while(p){
                while(p ->Rflag != 1){
                       p = p ->right;
                }
                printf("%c ",p ->data);
                while(p->Lflag == 1 && p ->left != NULL){
                        p = p ->left;
                        printf("%c ",p ->data);

                }
                p = p ->left;
        }
}
int main(){
        TreeNode T;
        TreeNode H;
        printf("请输入前序遍历的序列:\n");
        createTree(&T);
        printf("\n");

        mid_InThreading(T);
        printf("请输出中序线索化二叉树序列的序列:\n");
        mid_Search(T);
        printf("\n");

        //双向
        doubleReaction_Thread(&H,T);
        //正向遍历
   /*     printf("正向遍历: \n");
        zheng_Search(H);
        printf("\n");*/
        printf("逆向遍历: \n");
        ni_Search(H);

        return 0;

}

 

转载于:https://my.oschina.net/1024and1314/blog/3085588

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值