当前位置 博文首页 > Inmaturity_7的博客:408计算机考研--数据结构--线索化二叉树学

    Inmaturity_7的博客:408计算机考研--数据结构--线索化二叉树学

    作者:[db:作者] 时间:2021-07-16 21:46

    线索化二叉树学习(C语言)

    一、线索二叉树的基本概念

    ? 传统的二叉链表存储仅能体现一种父子关系,不能直接得到结点在遍历中的前驱或后继。我们知道,在含n个结点的二叉树中,有n+1个空指针。利用这些空指针来存放其前驱或后继的指针,这样就可以使得我们在遍历二叉树时可以像遍历单链表那样方便。引入线索二叉树正是为了加快查找结点前驱和后继的速度。(有三种线索化二叉树,分别是先序线索化二叉树、中序线索化二叉树以及后序线索化二叉树)

    二、中序线索化二叉树创建、找前驱、找后继以及遍历

    #include<stdio.h>
    #include<stdlib.h>
    
    
    //二叉树结构 
    typedef struct ThreadNode{
    	int data;
    	struct ThreadNode *lchild,*rchild;//左右孩子指针 
    	int ltag,rtag;//左右孩子线索标志 
    }ThreadNode,*ThreadTree;
    //中序遍历线索化二叉树的过程函数 
    void InThread(ThreadTree &p,ThreadTree &pre){
    	if(p!=NULL){
    		InThread(p->lchild,pre);
    		if(p->lchild==NULL){
    			p->lchild=pre;
    			p->ltag=1;
    		}
    		if(pre!=NULL&&pre->rchild==NULL){
    			pre->rchild=p;
    			pre->rtag=1;
    		}
    		pre=p;
    		InThread(p->rchild,pre);
    	}
    }
    //中序遍历建立中序线索二叉树 
    void CreateInThread(ThreadTree T){
    	ThreadTree pre=NULL;
    	if(T!=NULL){
    		InThread(T,pre);
    		pre->rchild==NULL; 
    		pre->rtag=1;
    	}
    }
    
    //访问结点函数
    void visit(ThreadTree T){
    	printf("%d->",T->data);//打印结点数据 
    }
    
    //找到以p为根的子树第一个被中序遍历的结点
    ThreadNode *FirstNode(ThreadNode *p){
    	//循环找到最左下结点(不一定是叶结点)
    	while(p->ltag==0){
    		p=p->lchild;
    	} 
    	return p; 
    } 
    //在中序线索二叉树中找到结点p的后继结点
    ThreadNode *NextNode(ThreadNode *p){
    	//右子树中最左下结点
    	if(p->rtag==0){
    		return FirstNode(p->rchild);
    	}else{
    		return p->rchild;//rtag==1直接返回后继线索 
    	}
    }
    //对中序线索二叉树进行中序遍历(利用线索实现的非递归算法) 
    void InOrder(ThreadNode *T){
    	for(ThreadNode *p=FirstNode(T);p!=NULL;p=NextNode(p)){
    		visit(p);
    	}
    }
    
    //找到以P为根的子树中,最后一个被中序遍历的结点
    ThreadNode *LastNode(ThreadNode *p){
    //循环找到最右下结点(不一定是叶结点)
     while(p->rtag==0){
     	p=p->rchild;
     } 
     return p;
    } 
    //在中序线索二叉树中找到结点p的前驱结点
    ThreadNode *PreNode(ThreadNode *p){
    	//左子树中最右下结点
    	if(p->ltag==0){
    		return LastNode(p->lchild);
    	}else{
    		return p->lchild;//ltag==1直接返回前驱线索 
    	}
    } 
    //对中序线索二叉树进行逆向中序遍历
    void ReInOrder(ThreadNode *T){
    	for(ThreadNode *p=LastNode(T);p!=NULL;p=PreNode(p))
    		visit(p);
    } 
    
    int main(){
    	//测试结点数据 
    	ThreadTree t1=(ThreadTree)malloc(sizeof(ThreadNode));
    	ThreadTree t2=(ThreadTree)malloc(sizeof(ThreadNode));
    	ThreadTree t3=(ThreadTree)malloc(sizeof(ThreadNode));
    	ThreadTree t4=(ThreadTree)malloc(sizeof(ThreadNode));
    	ThreadTree t5=(ThreadTree)malloc(sizeof(ThreadNode));
    	
    	t1->data=1;t1->lchild=t2;t1->rchild=t3;t1->ltag=t1->rtag=0;
    	t2->data=2;t2->lchild=t4;t2->rchild=t5;t2->ltag=t2->rtag=0;
    	t3->data=3;t3->lchild=NULL;t3->rchild=NULL;t3->ltag=t3->rtag=0;
    	t4->data=4;t4->lchild=NULL;t4->rchild=NULL;t4->ltag=t4->rtag=0;
    	t5->data=5;t5->lchild=NULL;t5->rchild=NULL;t5->ltag=t5->rtag=0;
    	//线索化二叉树 
    	CreateInThread(t1);
    	//中序(顺序)打印 
    	InOrder(t1); 
    	printf("\n");
    	//中序(逆序)打印
    	ReInOrder(t1);
    } 
    

    三、前中后序线索化二叉树的找前驱、找后继比较

    中序线索二叉树先序线索二叉树后序二叉树
    找前驱×
    找后继×
    cs