二叉树的相关操作(C语言)

上一篇文章中给出了用二叉树实现对单词的排序,它区别于更早之前编写的对单词的一般排序方法,在单词乱序的情况下,排序效率还是比较高的。这次笔者又学习了二叉树的一些新的操作,代码如下:

/* 二叉树的一系列基本操作 */

typedef struct TreeNote {
	char c;
	struct TreeNote *left;
	struct TreeNote *right;
	int Ltag;                           /* 用于线索二叉树 */
	int Rtag;
} TreeNote;

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

TreeNote *talloc(void);
void Create_BTree(TreeNote *&p);
void MidTravel_BTree(TreeNote *p);
int depth(TreeNote *p);
int NoteCount(TreeNote *p);
void CopyTree(TreeNote *p, TreeNote *&newp);
//void Mid_Threading(TreeNote *p, TreeNote *&head);       /* 中序线索化 */
TreeNote *Mid_Threading(TreeNote *p);
void Mid_Thread(TreeNote *&p);                
void Mid_Thread_Tree_Travel(TreeNote *head);

int main()
{
	TreeNote *heading;
	TreeNote *root = NULL;
	TreeNote *newroot = NULL;
	Create_BTree(root);
	MidTravel_BTree(root);               /* 中序遍历二叉树 */
	heading = Mid_Threading(root);        /* 中序线索化 Mid_Threading(root, head); */
	printf("\n");
	MidTravel_BTree(heading);               /* 中序遍历二叉树 */
//	MidTravel_BTree(head);               /* 中序遍历线索二叉树 */
	getchar();
	return 0;
}

/*
 *      分配内存
 */
TreeNote *talloc(void)
{
	TreeNote *p;
	p = (TreeNote *)(malloc(sizeof(TreeNote)));
	if(p == NULL) {
		printf("Out of space");
		return NULL;
	}
	return p;
}

/*
 *      先序建立二叉树
 */
void Create_BTree(TreeNote *&p)         /*传递的参数为 指向指针的引用(指针的别名),修改此引用不仅可以修改被引用的指针,而且可以求改被引用指针指向的内容 */
{
	char a, tmp;
	scanf("%c", &a);
	tmp = getchar();
	if('0' == a)
		p = NULL;
	else {
		p = talloc();
		p->c = a;
		printf("Enter %c left note : ", a);
		Create_BTree(p->left);
		printf("Enter %c right note : ",a);
		Create_BTree(p->right);
	}
}

/*
 *      中序遍历二叉树
 */
void MidTravel_BTree(TreeNote *p)
{
	if(p == NULL)
	return;
	else {
		MidTravel_BTree(p->left);
		printf("%c", p->c);  //printf("%c %d %d", p->c,p->Ltag, p->Rtag);
		MidTravel_BTree(p->right);
	}
}

/*
 *      以节点 p 为根的中序线索化
 */
TreeNote *pre;                          /* 全局变量,指向前一个节点 TreeNote *pre = talloc(); 好像可以不分配内存空间 */
                                        //pre->right = NULL;                              为什么不能放在外面  ?????? 
void Mid_Thread(TreeNote *&p)
{
	if(p) {
		Mid_Thread(p->left);           /* 左子树线索化 */
		if(p->left == NULL) {          /* p在后面,找它的前驱 */
			p->Ltag = 1;
			p->left = pre;
		}
		else 
			p->Ltag = 0;
		if(pre->right == NULL) {       /* pre在前面,找它的后继 */
			pre->Rtag = 1;
			pre->right = p;
		}
		else 
			p->Rtag = 0;
		pre = p;
		Mid_Thread(p->right);          /* 右子树线索化 */
	}
}

/*
 *      带头节点中序线索化
 */
TreeNote *Mid_Threading(TreeNote *p)
{
	TreeNote *head;
//	pre->right = NULL;                            /* 便于在树的最左点开始建线索 */
	head = talloc();
	head->Ltag = 0;                   /* 头节点有左孩子 */
	head->Rtag = 1;                   /* 头节点右指针为右线索,指向后继 */
	head->right = head;               /* 头节点右指针指向自己 */
	pre = head;
	if(NULL == p) {
		head->left = head;
//		return;
	} else {
		head->left = p;
		pre = head;
		Mid_Thread(p);                /* 函数结束后pre指向树的最右端的节点 */
		pre->Rtag = 1;                /* pre 的右指针线索化 */
		pre->right = head;            /* pre 的右指针指向后继head */
		head->right = pre;            /* head 的有指针(已经线索化了)指向树的最右边的节点 */
	}
	return head;
}

/*
 *      遍历中序线索二叉树
 */
void Mid_Thread_Tree_Travel(TreeNote *head)         /* head 为头结点的地址 */
{
	TreeNote *p;
	p = head->left;                                 /* p 指向根节点 */
	while (p != head) {
		while (p->Rtag == 0)
			p = p->left;
		printf("%c", p->c);
		while (p->Rtag == 1 && p->right != head) {
			p = p->right;
			printf("%c",p->c);
		}
		p = p->right;
	}
}

/*
 *      计算二叉树的深度
 */
int depth(TreeNote *p)
{
	int a, b;
	if(NULL == p)
		return 0;
	else {
		a = depth(p->left);
		b = depth(p->right);
		return a>b ? a+1 : b+1;              /*如果不加1,返回值一定为0,因为没有对对深度进行计数 */
	}                                        /* + 1 的作用是,每递归一层说明树的深度 +1 */
}

/*
 *      计算二叉树的节点个数
 */
int NoteCount(TreeNote *p)
{
	if(NULL == p)
		return 0;
	else
		return (NoteCount(p->left) + NoteCount(p->right)) +1;
}

/*
 *      先序复制二叉树
 */
void CopyTree(TreeNote *p, TreeNote *&newp)
{
	if(NULL == p) {
		newp = NULL;
		return;
	} else {
		newp = talloc();
		newp->c = p->c;
		CopyTree(p->left, newp->left);
		CopyTree(p->right, newp->right);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值