树---二叉树,线索二叉树,中序遍历线索二叉树

问题:

创建一个线索二叉树,并将其中进行线索化。任给一个结点找到结点的中序前驱和中序后继。

算法分析:

第一步创建二叉树结构:

  1. 根据输入一个广义表来创建二叉树(A(B(D,E(H)),C(F(,I),G))),使用二叉树的链式表示,左右孩子表示法;
  2. 用一个栈来存“(”后面的字母的指针,遇见“)”回退top–,再等于向top-1的指针
  3. 遍历广义表字符串,令pre指向树的头结点,开始遍历,遇见“(”或“,”,往前走一步i++;遇见每个字母,申请一块内存p,判断i-1是否为“(”,是则pre->lchild =p,p入栈;若为“,”,则pre->rchild = p;

第二步按照中序进行遍历,线索化:

  1. 左子树线索化:
  2. 找到最左下端结点,访问:
  3. 右子树线索化

第三步按照前驱后继进行访问:

代码:

#include "pch.h"
#include <iostream>
#include <stdio.h>
#include<stdlib.h>
constexpr auto MAXSIZE = 100;
typedef enum {Link,Thread} PointerTag;
typedef char DataType;
typedef struct Node // 定义线索二叉树存储类型
{
	PointerTag LTag;
	PointerTag RTag;
	DataType data;
	struct Node * lchild, *rchild;
} BiThrNode, *BiThrTree ;

BiThrNode *pre;

typedef struct 
{
	BiThrTree stack[MAXSIZE]; //存储树的结点指针
	int top;//栈顶指针
}Stack;

void CreateBitree(BiThrTree * T, char * str)//创建线索二叉树
{
	BiThrNode * pre,*p;
	pre = NULL;
	Stack PointerStack;
	PointerStack.top = 0; //初始化栈
	int i;
	for (i = 0; i < strlen(str); i++)
	{
		if (str[i] == '(' || str[i] == ',')
		{
			continue;
		}
		else if(str[i] == ')')
		{
			PointerStack.top--;
			if (PointerStack.top > 0)
			{
				pre = PointerStack.stack[PointerStack.top - 1];
			}
			

		}
		else //为字母
		{
			//将第一个字母作为根节点
			if (i == 1)
			{
				(*T )= (BiThrNode*)malloc(sizeof(BiThrNode));//申请一块结点的内存
				(*T)->LTag = (*T)->RTag = Link;//初始化
				(*T)->lchild = (*T)->rchild = NULL;
				(*T)->data = str[i];
				p = pre = (*T);
			}
			else
			{
				p = (BiThrNode*)malloc(sizeof(BiThrNode));//申请一块结点的内存
				p->LTag = p->RTag = Link;//初始化
				p->lchild = p->rchild = NULL;
				p->data = str[i];

				if (str[i - 1] == '(')
				{
					pre->lchild = p;
					

				}
				if (str[i - 1] == ',')
				{
					pre->rchild = p;
					pre = p;// 更新pre
				}
				
			}
			if (str[i + 1] == '(')//字母后面为'('。则将该字母入栈
			{
				PointerStack.stack[PointerStack.top++] = p;
				pre = p;
			}
		}

	}

}

void PrintBiTree(BiThrTree T) //打印二叉树
{
	BiThrNode *p;
	p = T;
	if (p)
	{
		printf("%c", p->data);
		PrintBiTree(p->lchild);
		PrintBiTree(p->rchild);

	}
}

void InThreading(BiThrTree T) //二叉树线索化
{
	BiThrNode* p;
	p = T;
	if (p)
	{
		InThreading(p->lchild);//左子树线索化
		if (!p->lchild)//前驱线索化
		{
			p->LTag = Thread;
			p->lchild = pre;
		}
		if (!pre->rchild)//后继线索化
		{
			pre->RTag = Thread;
			pre->rchild = p;
		}
		pre = p;
		InThreading(p->rchild);//右子树线索化
	}
	
	
}


void InOderThreading(BiThrTree *Thr,BiThrTree T)//通过中序遍历二叉树T,使T中序线索化
{
	
	//创建一个头节点
	if (!((*Thr) = (BiThrTree)malloc(sizeof(BiThrNode))))
		exit(-1);
	(*Thr)->data = 0;
	(*Thr)->LTag = Link;
	(*Thr)->RTag = Thread;
	(*Thr)->rchild = (*Thr);//修改后继线索标志
	if (!T)//如果二叉树为空,将头结点的左指针指向自己
	{
		(*Thr)->lchild = (*Thr);
	}
	else
	{
		(*Thr)->lchild = T;
		pre = (*Thr);//将pre指向已经线索化的结点
		InThreading(T);//中序遍历线索化
		pre->rchild = (*Thr);
		pre->LTag = Thread;
		(*Thr)->rchild = pre;
	}

}

int InorderTraverse(BiThrTree T, int(*visit) (BiThrNode *e))
//遍历线索二叉树,visit为函数指针,指向访问结点函数的实现
{

	BiThrTree p;
	p = T->lchild;
	while (p != T) //空树遍历结束时p=T
	{
		while (p->LTag == Link)//找到最下端的结点
			p = p->lchild;
		if (!visit(p)) //打印
			return 0;
		while (p->RTag == Thread && p->rchild != T)
		{
			p = p->rchild;
			visit(p);
		}
		p = p->rchild;
	}
	return 1;
}

int Print(BiThrTree T)
//打印结点信息
{
	static int k = 1;
	printf("%2d\t %s\t %2c\t %s\t\n", k++, T->LTag == Link ? "Link" : "Thread", T->data, T->RTag == Thread ? "Thread" : "Link");
	return 1;
}

BiThrNode * InOrderFind(BiThrTree  Thr , DataType e)
//查找结点
{
	BiThrNode *p;
	p = Thr->lchild;//指向根结点
	if (!p)
		return NULL;
	while (p!=Thr)
	{
		while (p->LTag == Link) //找到最左端结点
		{
			p = p->lchild;
		}
		if (p->data == e)
		{
			return p;
		}
		while (p->RTag == Thread && p->rchild != Thr) //往后走
		{
			p = p->rchild;
			if (p->data == e)
			{
				return p;
			}
		}
		p = p->rchild;//如果右边是LINK
	}
}

BiThrNode* InOrderPrev(BiThrTree T)
//找到P结点的中继前驱
{
	BiThrNode * p;
	p = T;
	if (p->LTag == Thread)
	{
		return p->lchild;
	}
	p = p->lchild;//找到左子树的最右边下端点
	while (p->RTag == Link)
	{
		p = p->rchild;
	}
	return p;
}

BiThrNode* InOrderPost(BiThrTree T)
//找到p结点的后继
{
	BiThrNode * p;
	p = T;
	if (p->RTag == Thread)
	{
		return p->rchild;
	}  
	p = p->rchild;
	while (p->RTag == Link)//找到右子树的最左下端结点
	{
		p = p->lchild;
	}
	return p;
}


int main()
{
	
	BiThrTree T,Thr;
	BiThrNode *p,*post,*prev;
	char str[MAXSIZE] = "(A(B(D,E(H)),C(F(,I),G)))";
	CreateBitree(&T, str);
	printf("二叉树:\n");
	PrintBiTree(T);//打印二叉树
	printf("\n");
	InOderThreading(&Thr, T);//线索化
	printf("中序线索化后的二叉树:\n");
	InorderTraverse(Thr, Print);//遍历按中序打印
	char c;
	printf("输入需要查找前驱后后继结点的结点\n");
	c = getchar();
	p = InOrderFind(Thr, c);
	if (p)
	{
		printf("打印找到的结点:\n");
		Print(p);
	}
	prev = InOrderPrev(p);
	post = InOrderPost(p);

	if (prev)
	{
		printf("打印P结点的前驱结点:\n");
		Print(prev);
	}
	
	if (prev)
	{
		printf("打印P结点的后继结点:\n");
		Print(post);
	}
	


	return 0;
}
 

程序运行截图:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_38904904/article/details/89110636