二叉树的基本操作

#include<stdio.h>
#include<stdlib.h>
#include"squeue.h"
#define Status int
#define OK 1
Status CreateBiTree(BiTree *T)
{
	char ch;
	scanf("\n%c", &ch);
	if (ch == '#') 
		*T = NULL;
	else
	{
		(*T) = (BiTree)malloc(sizeof(BiTNode));
		(*T)->data = ch;
		printf("输入%c的左子结点:", ch);
		CreateBiTree(&(*T)->lchild);
		printf("输入%c的右子结点:", ch);
		CreateBiTree(&(*T)->rchild);
	}
	return OK;
}
void PreOrderTraverse(BiTree T)
{
	if (T == NULL) return;
	printf(" %2c ", T->data);
	PreOrderTraverse(T->lchild);
	PreOrderTraverse(T->rchild);
}
void InOrderTraverse(BiTree T)
{
	if (T == NULL) return;
	InOrderTraverse(T->lchild);
	printf(" %2c ", T->data);
	InOrderTraverse(T->rchild);
}
void PostOrderTraverse(BiTree T)
{
	if (T == NULL) return;
	PostOrderTraverse(T->lchild);
	PostOrderTraverse(T->rchild);
	printf(" %2c ", T->data);
}

//叶子数
int LeafCount(BiTree T)
{
	int num1, num2;
	if (T == NULL) return 0;
	else if (T->lchild == NULL&&T->rchild == NULL) return 1;
	else
	{
		num1 = LeafCount(T->lchild);
		num2 = LeafCount(T->rchild);
		return (num1 + num2);
	}
}

//树的深度
int TreeDeep(BiTree T)
{
	int deep = 0;
	if (T)
	{
		int LeftDeep = TreeDeep(T->lchild);
		int RightDeep = TreeDeep(T->rchild);
		deep = LeftDeep > RightDeep ? LeftDeep + 1 : RightDeep + 1;
	}
	return deep;
}

BiTNode *Swap(BiTree T)
{//交换左右子树,不破坏原二叉树
	BiTree t, t1, t2;
	if (T == NULL) t = NULL;
	else
	{
		t = (BiTree)malloc(sizeof(BiTNode));
		t->data = T->data;
		t1 = Swap(T->lchild);
		t2 = Swap(T->rchild);
		t->lchild = t2;
		t->rchild = t1;
	}
	return t;
}
void InOrderTraverse2(BiTree T)
{
	SqStack S;
	BiTree p;
	InitStack(&S);//栈初始化
	p = T;
	while (p != NULL||S.top!=-1)
	{
		if (p != NULL)
		{
			Push(&S, p);
			p = p->lchild;
		}
		else
		{
			p=Pop(&S);
			printf(" %2c ", p->data);
			p = p->rchild;
		}
	}
}
void CopyTree(BiTree S, BiTree *P)
{
	if (S == NULL)
		*P = NULL;
	else
	{
		*P = (BiTree)malloc(sizeof(BiTNode));
		(*P)->data = S->data;
		CopyTree(S->lchild, &(*P)->lchild);
		CopyTree(S->rchild, &(*P)->rchild);
	}
}
int main()
{
	int cord,deep,N;
	BiTree T, P,M;
	do
	{
		printf("\n\n1.创建二叉树\n");
		printf("2.先序遍历\n");
		printf("3.中序遍历\n");
		printf("4.后序遍历\n");
		printf("5.叶子数\n");
		printf("6.树的深度\n");
		printf("7.交换左右子树\n");
		printf("8.非递归中序遍历\n");
		printf("9.二叉树复制\n");
		scanf("%d", &cord);

		switch (cord)
		{
		case 1:
		{printf("输入根节点的值,#表示没有叶结点\n");
		if (CreateBiTree(&T))printf("创建成功\n");
		}break;
		case 2:{printf("先序遍历二叉树:\n"); PreOrderTraverse(T); }break;
		case 3:{printf("中序遍历二叉树:\n"); InOrderTraverse(T); }break;
		case 4:{printf("后序遍历二叉树:\n"); PostOrderTraverse(T); }break;
		case 5:{N = LeafCount(T); printf("树的叶子结点个数为:%d", N); }break;
		case 6:{deep = TreeDeep(T); printf("\n树的深度为%d ", deep); }break;
		case 7:{	
				   P = Swap(T);
				   printf("交换后的前序遍历为:\n");
				   PreOrderTraverse(P);
				   printf("\n交换后的中序遍历为:\n");
				   InOrderTraverse(P);
				}break;
		case 8:
		{
				  printf("非递归的中序遍历为:\n");
				  InOrderTraverse2(T);
		}break;
		case 9:
		{

				  CopyTree(T, &M);
				  PreOrderTraverse(M);
		}break;
		}

	} while (cord < 9);
	return 0;
}


//squeue.h
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 30
typedef struct BiTNode
{
	char data;
	struct BitNode *lchild, *rchild;
}BiTNode, *BiTree;
typedef struct SqStack
{
	BiTNode *data[MAXSIZE];
	int top;
}SqStack;
void InitStack(SqStack *S)
{
	S->top = -1;
}
void Push(SqStack *S,BiTNode *x)
{
	if (S->top == MAXSIZE - 1){ printf("栈满无法入栈\n"); }
	else
	{
		S->top++;
		S->data[S->top] = x;
	}
}
BiTNode *Pop(SqStack *S)
{
	BiTNode *x;
	if (S->top == -1)
	{
		printf("栈是空的\n"); return NULL;
	}
	else
	{
		x = S->data[S->top];
		S->top--;
		return x;
	}

}




线索化二叉树

if(!p->lchild)表示如果某结点的左指针域为空,因为其前驱结点刚刚访问过,赋值了pre,所以可以将pre赋值给p->lchild,并修改p->ltag = Thread(也就是定义为1)以完成前驱结点的线索化。

    后继就麻烦一些。因为此时p结点的后继还没有访问到,因此只能对它的前驱结点pre的右指针rchild做判断,if(!pre->rchild)表示如果为空,则p就是pre的后继,于是pre->rchild = p,并且设置pre->rtag = Thread,完成后继结点的线索化。

    完成前驱和后继的判断后,不要忘记当前结点p赋值给pre,以便于下一次使用。


#include<stdio.h>
#include<stdlib.h>
#define Status int
#define OK 1
typedef enum  {Link, Thread }PointerTag;
typedef struct BiThrNode
{
	char data;
	struct BiThrNode *lchild, *rchild;
	PointerTag LTag, RTag;
}BiThrNode,*BiThrTree;
BiThrTree pre;
Status Create(BiThrTree *T)
{
	char ch;
	scanf("\n%c", &ch);
	if (ch == '#')
		*T = NULL;
	else
	{
		*T = (BiThrTree)malloc(sizeof(BiThrNode));
		(*T)->data = ch;
		printf("输入%c的左子节点:", ch);
		Create(&(*T)->lchild);
		printf("输入%c的右子节点:", ch);
		Create(&(*T)->rchild);
	}
	return OK;
}
void InThreading(BiThrTree p)
{
	if (p)
	{
	InThreading(p->lchild);//递归左子树线索化
		if (!p->lchild )
		{
			p->LTag = Thread;
			p->lchild = pre;//左孩子指针指向前驱
		}
		else p->LTag = 0;
		if (!pre->rchild)//前驱没有右孩子
		{
			pre->RTag = Thread;
			pre->rchild = p;
		}
		else p->RTag = 0;
		pre = p;
		InThreading(p->rchild);//递归右子树线索化
	}
}
Status InOrderThreading(BiThrTree *Thrt, BiThrTree T)
{//中序遍历二叉树T,并将其线索化,Thrt指向头结点
	*Thrt = (BiThrTree)malloc(sizeof(BiThrNode));
	(*Thrt)->LTag = Link;	(*Thrt)->RTag = Thread;//建立头结点
	(*Thrt)->rchild = *Thrt;	//右指针回指
	if (!T) (*Thrt)->lchild = (*Thrt);//若二叉树为空,则左指针回指
	else
	{
		(*Thrt)->lchild = T; pre = *Thrt;
		InThreading(T);
		pre->rchild = *Thrt;	pre->RTag = Thread;//最后一个结点线索化
		(*Thrt)->rchild = pre;
	}
	return OK;
}
Status InOrderTraverse(BiThrTree Thrt)
{
	BiThrTree p;
	p = Thrt->lchild;//p指向根结点
	while (p != Thrt)//空树或遍历结束时,p==T
	{
		while (p->LTag == Link) 
			p = p->lchild;
		printf(" %c ", p->data);
		while (p->RTag == Thread && p->rchild != Thrt)
		{
			p = p->rchild;
			printf("%c", p->data);
		}
		p = p->rchild;
	}
	return OK;
}
int main()
{
	BiThrTree T,Thrt;
	int cord;
	do
	{
		printf("\n\n1.二叉链表先序创建二叉树\n");
		printf("2.中序线索遍历\n");
		scanf("%d", &cord);
		switch (cord)
		{
		case 1:
		{printf("输入根节点的值,#表示没有叶结点\n");
		if (Create(&T))printf("创建成功\n");
		}break;
		case 2:{InOrderThreading(&Thrt, T);InOrderTraverse(Thrt); }break;
		}
	} while (cord <= 7);
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值