zoukankan      html  css  js  c++  java
  • 6.3线索二叉树(二叉树的线索化)

    6.3线索二叉树(二叉树的线索化)

    问题引入:以二叉链表作为存储结构时。仅仅能得到结点的左、右孩子的信息。不能得到直接前驱、后继的信息。

    问题解决:将二叉树线索化。

    实现原理:n个结点的二叉树具有n+1个空指针域。利用这些空指针域存储结点的前驱、后继信息。

    实质:线索化的实质是将二叉链表中的空指针改为指向前驱、后继的线索。


    (1)二叉树的存储表示

    enum {link,thread};//link=0; thread=1;
    typedef struct bintree
    {
    	char data;
    	struct bintree *lchild, *rchild;
    	int ltag,rtag;//标志域。

    指示 指针或线索 }BiNode, *BiTree;


    (2)二叉树的创建

    6.1二叉树的创建章节。


    (3)中序线索化 及 遍历(注意凝视内容)

    BiTree inorder_threading(BiTree thrt,BiTree t)
    {
    	thrt = (BiTree )malloc(len);//建立头指针
    	if(!thrt)
    		exit(0);
    	thrt->rtag = thread;//右指针回指
    	thrt->rchild = thrt;
    	thrt->ltag = link;
    	if(!t)//若二叉树空。左指针回指
    		thrt->lchild = thrt;
    	else
    	{
    		thrt->lchild = t;
    		pre = thrt;
    
    		in_threading(t);//中序遍历进行中序线索化
    		
    		pre->rtag = thread;//最后一个节点线索化
    		pre->rchild = thrt;
    		thrt->rchild = pre;
    	}
    	return thrt;
    }
    void in_threading(BiTree p)
    {
    	if(p)
    	{
    		in_threading(p -> lchild);//左子树线索化
    		if(! p->lchild)//前驱线索
    		{
    			p->ltag = thread;
    			p->lchild = pre;
    		}
    		if(! pre->rchild)//后继线索
    		{
    			pre->rtag = thread;
    			pre->rchild = p;
    		}
    		pre = p;//保持pre指向 p 的前驱
    		in_threading(p->rchild);//右子树线索化
    	}
    }
    void inorder_traverse(BiTree thrt)
    {
    	BiTree p = thrt->lchild;
    	while(p != thrt)//空树或遍历结束时,p==thrt
    	{
    		while(p->ltag == link)
    		{
    			p = p->lchild;
    		}
    		printf("%c ",p->data);
    		if(p->rtag == thread && p->rchild != thrt)
    		{
    			p = p->rchild;
    			printf("%c ",p->data);
    		}
    		p = p->rchild;
    	}
    }


    (4)先序线索化 及 遍历

    BiTree preorder_threading(BiTree thrt,BiTree t)
    {
    	thrt = (BiTree )malloc(len);
    	if(! thrt)
    		exit(0);
    	thrt -> rtag = thread;
    	thrt -> rchild = thrt;
    	thrt -> ltag = link;
    
    	if(!t)
    		thrt -> lchild = thrt;
    	else
    	{
    		thrt -> lchild = t;
    		pre = thrt;
    
    		pre_threading(t);
    	
    		pre -> rtag = thread;
    		pre -> rchild = thrt;
    		thrt -> rchild = pre;
    	}
    	return thrt;
    }
    void pre_threading(BiTree p)
    {
    	if(p)
    	{
    		if(! p->lchild)
    		{
    			p -> ltag = thread;
    			p -> lchild = pre;
    		}
    		if(!p -> rchild)
    			p -> rtag = thread;
    		if(pre && pre->rtag == thread)
    			pre -> rchild = p;
    		pre = p;
    		if(p->ltag == link)
    			pre_threading(p -> lchild);
    		if(p->rtag == link)
    			pre_threading(p -> rchild);
    	}
    }
    void preorder_traverse(BiTree thrt)
    {
    	BiTree p = thrt -> lchild;
    
    	printf("%c ",p->data);
    	while(p->rchild != thrt)
    	{
    		if(p->ltag == link)
    			p = p->lchild;
    		else
    			p = p->rchild;
    
    		printf("%c ",p->data);
    	}
    }


    (5)后序线索化 及 遍历
    BiTree postorder_threading(BiTree thrt,BiTree t)
    {
    	thrt = (BiTree )malloc(len);
    	if(! thrt)
    		exit(0);
    	thrt -> rtag = thread;
    	thrt -> rchild = thrt;
    	thrt -> ltag = link;
    
    	if(!t)
    		thrt -> lchild = thrt;
    	else
    	{
    		thrt -> lchild = t;
    		pre = thrt;
    
    		post_threading(t);
    	
    		pre -> rtag = thread;
    		pre -> rchild = thrt;
    		thrt -> rchild = pre;
    	}
    	return thrt;
    }
    void post_threading(BiTree p)
    {
    	if(p)
    	{
    		post_threading(p->lchild);   //左子树线索化
            post_threading(p->rchild);   //右子树线索化
    		if(!p->lchild)
    		{
    			p->ltag=thread;
    			p->lchild=pre;
    		}
    		if(!pre->rchild)
    		{
    			pre->rtag=thread;
    			pre->rchild=p;
    		}
    		pre=p;
    	}
    }
    void postorder_traverse(BiTree thrt)
    {
    	BiTree p = thrt;
    	
    	while(p->ltag==link||p->rtag==link)   //有左孩子先訪问左孩子,没有左孩子先訪问右孩子
    	{
    		while(p->ltag==link)    
    			p=p->lchild;
    		if(p->rtag==link)                //訪问左孩子为空的结点的右孩子
    			p=p->rchild;
    	}
    	printf("%c ",p->data);
    	while(p!=T)                        //p不为根结点
    	{ 
    		if(p->rtag==link)              //若p是有兄弟的左孩子
    		{ 
    			if(pre->rtag==thread||p==pre->rchild) //若p是双亲的右孩子或是独生左孩子,则后继为双亲
    				p=pre;
    			else 
    			{ 
    				p=pre->rchild;              //后继为双亲的右子树上依照后序遍历訪问的第一个结点。
    				while(p->ltag==link||p->rtag==link)
    				{ 
    					while(p->ltag==link) 
    						p=p->lchild;
    					if(p->rtag==link)
    						p=p->rchild;
    			    }
    			}
    		}
    		else 
    			p=p->rchild;             //p指向后继
    	
    		printf("%c ",p->data);
    	}
    } 
    


    (6)总程序源码(.c)

    					/*  例子输入: abc##de#g##f###  */
    # include <stdio.h>
    # include <stdlib.h>
    # define len (sizeof(BiNode))
    # define OK 1
    
    enum {link,thread};
    typedef struct bintree
    {
    	char data;
    	struct bintree *lchild, *rchild;
    	int ltag,rtag;
    }BiNode, *BiTree;
    
    BiTree T, thrt, pre;
    
    int bintree_creat(BiTree *q);
    void welcome(BiTree t);
    
    BiTree preorder_threading(BiTree thrt,BiTree t);//先序
    void pre_threading(BiTree p);
    void preorder_traverse(BiTree thrt);
    
    BiTree inorder_threading(BiTree thrt,BiTree t);//中序 
    void in_threading(BiTree p);
    void inorder_traverse(BiTree thrt);
    
    BiTree postorder_threading(BiTree thrt,BiTree t);//后序
    void post_threading(BiTree p);
    void postorder_traverse(BiTree thrt);
    
    int main()
    {
    	printf("now create the bintree first,please input :
    ");
    	bintree_creat(&T);
    
    	welcome(T);
    
    	return 0;
    }
    
    int bintree_creat(BiTree *q)
    {
    	char ch;
    	ch=getchar();
    
    	if(ch=='#')
    		(*q)=NULL;
    	else
    	{
    		(*q) = (BiTree )malloc(len);
    		if((*q))
    		{
    			(*q)->data = ch;
    			(*q)->ltag = link;
    			(*q)->rtag = link;
    			bintree_creat(&(*q) -> lchild);
    			bintree_creat(&(*q) -> rchild);
    		}
    	}
    
    	return OK;
    }
    
    void welcome(BiTree t)
    {
    	int i;
    	printf("input 1 :preorder_threading the bintree .
    ");
    	printf("input 2 :inorder_threading the bintree .
    ");
    	printf("input 3 :postorder_threading the bintree .
    
    ");
    	scanf("%d",&i);
    
    	switch (i)
    	{
    		case 1 :thrt = preorder_threading(thrt,t);
    				preorder_traverse(thrt);
    				printf("
    
    "); break;
    				
    		case 2 :thrt = inorder_threading(thrt,t);
    				inorder_traverse(thrt);
    				printf("
    
    "); break;
    
    		case 3 :thrt = postorder_threading(thrt,t);
    				postorder_traverse(thrt);
    				printf("
    
    "); break;
    
    		default :printf("input error !");
    				 exit(1);
    	}
    }
    
    BiTree preorder_threading(BiTree thrt,BiTree t)
    {
    	thrt = (BiTree )malloc(len);
    	if(! thrt)
    		exit(0);
    	thrt -> rtag = thread;
    	thrt -> rchild = thrt;
    	thrt -> ltag = link;
    
    	if(!t)
    		thrt -> lchild = thrt;
    	else
    	{
    		thrt -> lchild = t;
    		pre = thrt;
    
    		pre_threading(t);
    	
    		pre -> rtag = thread;
    		pre -> rchild = thrt;
    		thrt -> rchild = pre;
    	}
    	return thrt;
    }
    void pre_threading(BiTree p)
    {
    	if(p)
    	{
    		if(! p->lchild)
    		{
    			p -> ltag = thread;
    			p -> lchild = pre;
    		}
    		if(!p -> rchild)
    			p -> rtag = thread;
    		if(pre && pre->rtag == thread)
    			pre -> rchild = p;
    		pre = p;
    		if(p->ltag == link)
    			pre_threading(p -> lchild);
    		if(p->rtag == link)
    			pre_threading(p -> rchild);
    	}
    }
    void preorder_traverse(BiTree thrt)
    {
    	BiTree p = thrt -> lchild;
    
    	printf("%c ",p->data);
    	while(p->rchild != thrt)
    	{
    		if(p->ltag == link)
    			p = p->lchild;
    		else
    			p = p->rchild;
    
    		printf("%c ",p->data);
    	}
    }
    
    BiTree inorder_threading(BiTree thrt,BiTree t)
    {
    	thrt = (BiTree )malloc(len);//建立头指针
    	if(!thrt)
    		exit(0);
    	thrt->rtag = thread;//右指针回指
    	thrt->rchild = thrt;
    	thrt->ltag = link;
    	if(!t)//若二叉树空,左指针回指
    		thrt->lchild = thrt;
    	else
    	{
    		thrt->lchild = t;
    		pre = thrt;
    
    		in_threading(t);//中序遍历进行中序线索化
    		
    		pre->rtag = thread;//最后一个节点线索化
    		pre->rchild = thrt;
    		thrt->rchild = pre;
    	}
    	return thrt;
    }
    void in_threading(BiTree p)
    {
    	if(p)
    	{
    		in_threading(p -> lchild);//左子树线索化
    		if(! p->lchild)//前驱线索
    		{
    			p->ltag = thread;
    			p->lchild = pre;
    		}
    		if(! pre->rchild)//后继线索
    		{
    			pre->rtag = thread;
    			pre->rchild = p;
    		}
    		pre = p;//保持pre指向 p 的前驱
    		in_threading(p->rchild);//右子树线索化
    	}
    }
    void inorder_traverse(BiTree thrt)
    {
    	BiTree p = thrt->lchild;
    	while(p != thrt)//空树或遍历结束时,p==thrt
    	{
    		while(p->ltag == link)
    		{
    			p = p->lchild;
    		}
    		printf("%c ",p->data);
    		if(p->rtag == thread && p->rchild != thrt)
    		{
    			p = p->rchild;
    			printf("%c ",p->data);
    		}
    		p = p->rchild;
    	}
    }
    
    BiTree postorder_threading(BiTree thrt,BiTree t)
    {
    	thrt = (BiTree )malloc(len);
    	if(! thrt)
    		exit(0);
    	thrt -> rtag = thread;
    	thrt -> rchild = thrt;
    	thrt -> ltag = link;
    
    	if(!t)
    		thrt -> lchild = thrt;
    	else
    	{
    		thrt -> lchild = t;
    		pre = thrt;
    
    		post_threading(t);
    	
    		pre -> rtag = thread;
    		pre -> rchild = thrt;
    		thrt -> rchild = pre;
    	}
    	return thrt;
    }
    void post_threading(BiTree p)
    {
    	if(p)
    	{
    		post_threading(p->lchild);   //左子树线索化
            post_threading(p->rchild);   //右子树线索化
    		if(!p->lchild)
    		{
    			p->ltag=thread;
    			p->lchild=pre;
    		}
    		if(!pre->rchild)
    		{
    			pre->rtag=thread;
    			pre->rchild=p;
    		}
    		pre=p;
    	}
    }
    void postorder_traverse(BiTree thrt)
    {
    	BiTree p = thrt;
    	
    	while(p->ltag==link||p->rtag==link)   //有左孩子先訪问左孩子,没有左孩子先訪问右孩子
    	{
    		while(p->ltag==link)    
    			p=p->lchild;
    		if(p->rtag==link)                //訪问左孩子为空的结点的右孩子
    			p=p->rchild;
    	}
    	printf("%c ",p->data);
    	while(p!=T)                        //p不为根结点
    	{ 
    		if(p->rtag==link)              //若p是有兄弟的左孩子
    		{ 
    			if(pre->rtag==thread||p==pre->rchild) //若p是双亲的右孩子或是独生左孩子,则后继为双亲
    				p=pre;
    			else 
    			{ 
    				p=pre->rchild;              //后继为双亲的右子树上依照后序遍历訪问的第一个结点。
    				while(p->ltag==link||p->rtag==link)
    				{ 
    					while(p->ltag==link) 
    						p=p->lchild;
    					if(p->rtag==link)
    						p=p->rchild;
    			    }
    			}
    		}
    		else 
    			p=p->rchild;             //p指向后继
    	
    		printf("%c ",p->data);
    	}
    } 
    

    (7)撰写匆忙,表述简陋。必有疏漏。欢迎朋友们批评指正。

    2014/10/21




  • 相关阅读:
    拾遗:『rhel6系列的开、关机脚本』
    拾遗:{rpm、yum及源码方式管理软件包}
    拾遗:sed&vim
    拾遗:Linux 用户及权限管理基础
    『BASH』——Learn BashScript from Daniel Robbins——[003]
    『BASH』——Hadex's brief analysis of "Lookahead and Lookbehind Zero-Length Assertions"
    『BASH』——Learn BashScript from Daniel Robbins——[001-002]
    Modular arithmetic and Montgomery form 实现快速模乘
    __int128使用
    Windows10下安装CentOS7双系统
  • 原文地址:https://www.cnblogs.com/yxysuanfa/p/6962449.html
Copyright © 2011-2022 走看看