#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<string.h>
//typedef char ElemType;
#define MAXSIZE 60
typedef struct node
{
char data; //存放结点的值
struct node* lchild;//指向左孩子结点指针
struct node* rchild;//指向右孩子结点指针
}BTNode;
void InitBiTree(BTNode*& T)//初始化二叉树,用于构造一棵空的二叉树
{
T = NULL;
}
void CreateBiTree(BTNode*& T, char* str)//创建二叉树
{
//定义一个大小为MAXSIZE的存储二叉树结点的栈,p用来作为中间变量暂存结点再存放到栈中
BTNode* St[MAXSIZE], * p = NULL;
//top用来进行进栈、出栈之类的操作,tag用于判断是是栈中结点的左孩子还是右孩子
//tag==1时表明为这个结点为栈中结点的左孩子
//tag==2时表明这个结点作为栈中结点的右孩子结点
//j用于遍历字符串
int top = -1, tag=0, j = 0;
char ch;
T = NULL;//建立的二叉树初始时为空
ch = str[j];
while (ch != '\0')//str未扫描完时循环
{
switch (ch)
{
case'('://若为左括号的话则将top的值加一,将上一个已经开辟空间的p结点进行入栈操作,
{ //并将tag的值置为1,意为下一个是左孩子
top++;
St[top] = p;
tag = 1;
break;
}
case')'://如果是括号的话top的值减一,则相当于进行出栈操作
{
top--;
break;
}
case','://如果是逗号的话说明是右孩子,则将tag置为2
{
tag = 2;
break;
}
default://其它情况即为结点的数据值,比如字母A、B、C、D
{ //开辟空间,data域赋值,左右孩子结点域置空
p = (BTNode*)malloc(sizeof(BTNode));
p->data = ch;
p->lchild = p->rchild = NULL;
//若树为空则让p为根节点,否则就根据tag的值进行入栈操作
if (T == NULL)
{
T = p;
}
else
{
switch (tag)
{
case 1:
{
St[top]->lchild = p;
break;
}
case 2:
{
St[top]->rchild = p;
break;
}
}
}
}
}
j++;
ch = str[j];
}
}
void visite(BTNode*& T)//访问二叉树结点
{
if (T == NULL)
{
printf("The node does not exist\n");
}
else
{
printf("%c", T->data);
}
}
void PrintBiTree(BTNode*& T, int level)//横向输出二叉树,level初始值为0
{
if (T != NULL)
{
//因为根节点的左孩子和右孩子是在第二层,逻辑上要加一
PrintBiTree(T->rchild, level + 1);//注意是先迭代处理右子树再写下面的打印条件!!!
if (level != 0)//如果不是第一层的话就打空格和横线
{
for (int i = 0; i < 4 * (level - 1); i++)//走过4*(level-1)个空格
{
printf("%s", " ");
}
//printf("%s", " ");
//printf("%s", " ");
//printf("%s", " ");
printf("---");//输出横线
}
visite(T);
printf("\n");
PrintBiTree(T->lchild, level + 1);
}
}
void DestroyBiTree(BTNode*& T)//销毁二叉树
{
if (T != NULL)
{
DestroyBiTree(T->lchild);
DestroyBiTree(T->rchild);
free(T);
}
}
//找到特定值的结点,返回其双亲结点,使用外部输入和递归的方式
BTNode* Find(BTNode* &node, char value, BTNode** parent)
{
if (node == NULL)
{
return NULL;
}
if (node->data==value)//单个字符比较用两个等号判断
{
return *parent;
}
//如果不是该特定值结点的话,继续往下遍历非空结点的左右子树查找
else
{
BTNode* tempparent = node;
BTNode* FindDeeply = Find(node->lchild, value, &tempparent);//往更下面深层遍历二叉树递归查找
if (FindDeeply != NULL)
{
return FindDeeply;
}
//如果左子树遍历找不到的话再遍历右子树
return Find(node->rchild, value, &tempparent);
}
}
//整个完整查找特定结点的双亲结点的函数(要求通过根节点出发?)
BTNode* FindParent(BTNode* T, char value)
{
if (T->lchild->data == value || T->rchild->data == value)//
{
//printf("所求该结点的双亲结点为根结点\n");
return NULL;
}
if (T == NULL)
{
printf("二叉树为空,为无法查找\n");
return NULL;
}
if (T->lchild != NULL)
{
BTNode*Tleft = T->lchild;
if (Find(Tleft->lchild, value, &Tleft) != NULL)//一定要加这个条件判断,否则即使找到了并且成功返回了的话但
//该函数并不会成功结束并返回该指针,因为递归还没有结束,不加这个if的条件判断和操作的话会继续递归回到上一个线程则只能判断是右子树的结点了
{
return Find(Tleft->lchild, value, &Tleft);
}
else
{
Find(Tleft->rchild, value, &Tleft);
}
}
if (T->rchild != NULL)
{
BTNode* Tright = T->rchild;
if (Find(Tright->lchild, value, &Tright) != NULL)
{
return Find(Tright->lchild, value, &Tright);
}
else
{
Find(Tright->rchild, value, &Tright);
}
}
}
int main(int argc, char* argv[])
{
BTNode* T;
InitBiTree(T);
char str[] = "1(2,3(4(6),5))";//"A(B(D, E(G, )), C(, F))";
CreateBiTree(T, str);
PrintBiTree(T, 0);
char a;
printf("请输入你要查找的结点:");
scanf_s("%c",&a);
if (FindParent(T,a)!=NULL)
{
printf("结点%c的双亲结点是%c\n",a,FindParent(T,a)->data);
}
else
{
printf("无法查找该结点或该结点的双亲结点是根节点");
}
DestroyBiTree(T);
return 0;
}