线索二叉树的创建

二叉树一般创建时用前序遍历法,线索化时用中序遍历

线索二叉树:指向前驱后继的指针称为线索,加上线索的二叉链表为线索链表。

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

typedef char ElemType;
//线索存储标志位
//Link(0):表示指向左右孩子的指针
//Thread(1):表示指向前驱后继的指针
typedef enum{Link,Thread} PointTag;

//二叉线索存储结点结构
typedef struct BitThrNode  
{
	ElemType data;                     
	struct BitThrNode *lchild,*rchild;
	PointTag LTag,RTag;
}BitThrNode,*BitThrTree;
//pre始终指向刚刚访问过的节点
BitThrTree pre;
//全局变量:始终指向刚刚访问过的节点

//创建一棵二叉树,约定用户遵照前序遍历的方式输入数据
void CreateBitThrTree(BitThrTree *T)
{
	ElemType ch;
	scanf("%c",&ch);
	if(ch=='#')
		*T=NULL;
	else
	{
		*T=(BitThrTree)malloc(sizeof(BitThrNode));
		(*T)->data=ch;
		(*T)->LTag=Link;
		(*T)->RTag=Link;
		
		CreateBitThrTree(&(*T)->lchild);
		CreateBitThrTree(&(*T)->rchild);
	}
}
//中序遍历进行二叉树线索化
void InThreading(BitThrTree p)
{
	if(p)
	{
		InThreading(p->lchild);//递归左孩子线索化
		if(!p->lchild)         //如果该节点没有左孩子,设置ltag为thread,并把lchild指向刚刚访问的节点
		{
			p->LTag=Thread;
			p->lchild=pre;
		}
		if(!pre->rchild)
		{
			pre->RTag=Thread;
			pre->rchild=p;
		}
		pre=p;
		InThreading(p->rchild);//递归右孩子线索化
	}
}

void InOrderThreading(BitThrTree *p,BitThrTree T)
{
	*p=(BitThrTree)malloc(sizeof(BitThrNode));//创建头结点
	
	(*p)->LTag=Link;
	(*p)->RTag=Thread;
	(*p)->rchild=T;
	
	if(!T)
	{
		(*p)->lchild=*p;//空树指向本身
	}
	else
	{
		(*p)->lchild=T;
		pre=*p;
		InThreading(T);
		pre->rchild=*p;
		pre->RTag=Thread;
		(*p)->rchild=pre;
	}
	
}
void visit(char c)
{
	printf("%c",c);
}
//中序遍历二叉树,非递归
void InOrderThaverse(BitThrTree T)//T是一个头指针了
{
	BitThrTree p;//根节点
	p=T->lchild;
	
	while(p!=T)
	{
		while(p->LTag==Link)
		{
			p=p->lchild;
		}
		visit(p->data);
		while(p->RTag==Thread&&p->rchild!=T)
		{
			p=p->rchild;
			visit(p->data);
		}
		p=p->rchild;
	}
	
}
void main()
{
	BitThrTree p,T=NULL;//p是头指针,T是根节点
	
	CreateBitThrTree(&T);
	InOrderThreading(&p,T);
	printf("中序遍历结果:\n");
	InOrderThaverse(p);
}

运行输入:前序输入:ABC##D##E#F##

运行输出:中序输出:CBDAEF


另一种编程:

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

typedef char elemtype;

typedef enum{normal,thread}node_type_t;
typedef struct node_s node_t;



typedef struct
{
	node_t *ptr;
	node_type_t type;
}node_ptr_t;

struct node_s
{
	elemtype data;
	node_ptr_t right,left;	
	int visited;
};
node_ptr_t *wanted=NULL;
node_t *pre=NULL;

node_t *new_node(elemtype data)
{
	node_t *node=(node_t *)malloc(sizeof(node_t));
	
	node->data=data;
	node->right.ptr=NULL;
	node->right.type=normal;
	node->left.ptr=NULL;
	node->left.type=normal;
	node->visited=0;
	
	return node;
}
void creat_tree(node_t **node)
{
	elemtype ch;
	scanf("%c",&ch);
	if(ch==' ')
		return;
	else
	{
		*node=new_node(ch);
		creat_tree(&((*node)->left.ptr));
		creat_tree(&((*node)->right.ptr));
	}
}

void travel_in_order(node_t *node,void (*cb)(node_t *))
{
	if(!node)
		return;
	else
	{
		travel_in_order(node->left.ptr,cb);
		cb(node);
		travel_in_order(node->right.ptr,cb);
	}
} 

void print(node_t *node)
{
	putchar(node->data);
}

void inthreading(node_ptr_t ptr)
{
	node_t *node=ptr.ptr;
	if(!node||ptr.type==thread)
	return;
	
	if(!node->left.ptr)//左孩子没有
	{
		node->left.ptr=pre;	
		if(pre)
		{
			node->left.type=thread;
		}
			
	}
	inthreading(node->left);
	if(wanted)
	{
		wanted->ptr=node;
		wanted->type=thread;		
		wanted=NULL;
	}
	if(!node->right.ptr)//右孩子没有
	{
		wanted=&(node->right);
	}
	pre=node;
	inthreading(node->right);
	
}
is_visit(node_t *node)
{
	return node->visited;
}
is_thread(node_ptr_t ptr)
{
	return ptr.type==thread ;
}
void visit_threading(node_t *node)
{
	print(node);
	node->visited=1;
}
void travel_with_threading(node_t *node,void cb(node_t *))
{
	travel_left:
	while(node->left.ptr&&!is_visit(node->left.ptr)&&!is_thread(node->left))
	{
		node=node->left.ptr;
	}
	cb(node);
	if(node->right.ptr||is_thread(node->right))
	{
		node=node->right.ptr;
		goto travel_left;
	}
	
	
}
void main()
{
	node_t *p;
	node_ptr_t pp;
		
	creat_tree(&p);
	
	pp.ptr=p;
	pp.type=normal;
	
	travel_in_order(p,print);
	printf("\n");
	inthreading(pp);
	
	travel_with_threading(p,visit_threading);
}


中序线索二叉树是一种带附加信息的二叉搜索树,它在每个节点上添加了两个指针,一个是左线索(用于查找左子树),另一个是右线索(用于查找前驱或后继节点)。在中序遍历时,线索可以用来回溯,使得遍历过程更容易控制,特别是在构建和操作这样的树结构时。 在C语言中,你可以通过以下几个步骤创建一个中序线索二叉树: 1. 定义树节点结构体,包含值、左右子节点指针以及前驱和后继指针(如果不是叶子节点的话): ```c typedef struct TreeNode { int data; struct TreeNode* left; struct TreeNode* right; struct TreeNode* prev; // 左线索 struct TreeNode* next; // 右线索(仅对非叶节点有效) } Node; ``` 2. 创建函数用于插入节点,更新线索: ```c Node* insert(Node** root, int val) { if (*root == NULL) { *root = (Node*)malloc(sizeof(Node)); (*root)->data = val; (*root)->prev = (*root)->next = NULL; // 新增节点默认无前驱后继 } else if (val < (*root)->data) { (*root)->left = insert(&(*root)->left, val); (*root)->left->prev = (*root); // 更新左子树线索 if ((*root)->left != (*root)) (*root)->left->next = (*root); } else { (*root)->right = insert(&(*root)->right, val); if ((*root)->right != (*root)) { (*root)->right->prev = (*root); // 更新右子树线索 (*root)->right->next = (*root)->left; // 如果不是最后一个节点,则连接到左子树 } } return *root; } ``` 3. 示例插入操作: ```c Node* root = NULL; insert(&root, 5); // 插入根节点 insert(&root, 3); // 插入左子树 // ...以此类推 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值