二叉树的基本操作与应用

BTree.h

#ifndef AAA
#define AAA

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

typedef char DataType;

typedef struct BTreeNode
{
	DataType data;
	struct BTreeNode *left;
	struct BTreeNode *right;
}BTreeNode;

void CreatBTree(BTreeNode **cur, DataType *str, DataType invalid, int *index);
void Preorder(BTreeNode *cur);
void Inorder(BTreeNode *cur);
void Postorder(BTreeNode *cur);
void Destroy(BTreeNode **cur);
void CpBTree(BTreeNode *cur, BTreeNode **ret);
int BTreeHight(BTreeNode *cur);
int BTreeNum(BTreeNode *cur);
int BTree(BTreeNode *cur);
int BTreeKnum(BTreeNode *cur, int K);
BTreeNode *LeftNode(BTreeNode *cur, DataType data);
BTreeNode *RightNode(BTreeNode *cur, DataType  data);
BTreeNode* ParentNode(BTreeNode *cur, DataType  data);
#endif

BTree.c

#include"BTree.h"

//申请一个节点
BTreeNode *BuyBTreeNode(DataType data)
{
	BTreeNode *NewNode = (BTreeNode *)malloc(sizeof(BTreeNode));
	if(NULL == NewNode)
	{
		assert(0);
	}
	NewNode->data = data;
	NewNode->left = NULL;
	NewNode->right = NULL;
	return NewNode;
}
//构建树
void CreatBTree(BTreeNode **cur, DataType *str, DataType invalid, int *index)
{
	BTreeNode *ret = NULL;
	assert(cur&&str);
	if(str[*index] && invalid != str[*index])
	{
		(*cur) = BuyBTreeNode(str[*index]);
		(*index)++;
		CreatBTree(&(*cur)->left, str, invalid , index);
		if(str[*index] != '\0')
		{
			(*index)++;
			CreatBTree(&(*cur)->right, str, invalid , index);
		}
	}
}
//拷贝树
void CpBTree(BTreeNode *cur, BTreeNode **ret)
{
	assert(ret);
	if(cur)
	{
		(*ret) = BuyBTreeNode(cur->data);
		CpBTree(cur->left, &(*ret)->left);
		CpBTree(cur->right, &(*ret)->right);
	}
}
//前序遍历
void Preorder(BTreeNode *cur)
{
	if(cur)
	{
		printf("%c",cur->data);
		Preorder(cur->left);
		Preorder(cur->right);
	}
}
//中序
void Inorder(BTreeNode *cur)
{
	if(cur)
	{
		Inorder(cur->left);
		printf("%c",cur->data);
		Inorder(cur->right);
	}
}
//后序
void Postorder(BTreeNode *cur)
{
	if(cur)
	{
		Postorder(cur->left);
		Postorder(cur->right);
		printf("%c",cur->data);
	}
}
//销毁
void Destroy(BTreeNode **cur)
{
	BTreeNode *ret = *cur;
	assert(cur);
	if(*cur)
	{
		Destroy(&ret->left);
		Destroy(&ret->right);
		free(ret);
		ret = NULL;
	}
}
//求树的节点个数
int BTreeNum(BTreeNode *cur)
{
	if(cur == NULL)
		return 0;
	return BTreeNum(cur->left) + BTreeNum(cur->right) + 1;
}
//求树的高度
int BTreeHight(BTreeNode *cur)
{
	int lefthight = 0;
	int righthight = 0;
	if(NULL == cur)
		return 0;
	lefthight = BTreeHight(cur->left);
	righthight = BTreeHight(cur->right);

	return lefthight > righthight ? lefthight+1 : righthight+1;
}
//叶子节点
int BTree(BTreeNode *cur)
{
	if(NULL == cur)
		return 0;
	if(NULL == cur->left && NULL == cur->right)
		return 1;
	return BTree(cur->left)+BTree(cur->right);
}
//求第k层的节点
int BTreeKnum(BTreeNode *cur, int K)
{
	if(NULL == cur)
		return 0;
	if(K == 1)
		return 1;
	return BTreeKnum(cur->left,K-1) + BTreeKnum(cur->right,K-1);
}
//求一个节点的左孩子
BTreeNode *LeftNode(BTreeNode *cur, DataType  data)
{
	BTreeNode *ret = NULL;
	if(NULL == cur)
		return NULL;
    if(cur->data == data && cur->left != NULL)
	{
		return cur->left;
	}
	ret = LeftNode(cur->left, data);
		//如果左子数找到的话,就不用进右子树找了
	//如果左子数找不到的话,进入右子树找
	if(ret == NULL)
	   ret =  LeftNode(cur->right, data);
	return ret;
}
//求一个节点的右孩子
BTreeNode *RightNode(BTreeNode *cur, DataType  data)
{
	BTreeNode *ret = NULL;
	if(NULL == cur)
		return NULL;
    if(cur->data == data && cur->right != NULL)
	{
		return cur->right;
	}
	ret = RightNode(cur->left, data);
		//如果左子数找到的话,就不用进右子树找了
	//如果左子数找不到的话,进入右子树找
	if(ret == NULL)
	   ret =  RightNode(cur->right, data);
	return ret;
}
//求一个节点的双亲节点
BTreeNode* ParentNode(BTreeNode *cur, DataType  data)
{
	BTreeNode *ret = NULL;
	if(cur->data == data)
		return NULL;
	if(cur->left->data == data|| cur->right->data == data)
		return cur;
	ret = ParentNode(cur->left, data);
	//如果左子数找到的话,就不用进右子树找了
	//如果左子数找不到的话,进入右子树找
	if(ret == NULL)
	   ret =  ParentNode(cur->right, data);
	return ret;
}

Main.c

#include"BTree.h"

void Text()
{
	BTreeNode *cur = NULL;
	BTreeNode *ret = NULL;
	BTreeNode *e = NULL;
	int hight = 0;
	int num = 0;
	int a = 0;
	DataType str[] = "ABD###CE##F";
	DataType invalid = '#';
	int index = 0;
	int Knum = 0;
	//创建树
	CreatBTree(&cur, str, invalid, &index);
	//拷贝树
	CpBTree(cur, &ret);
	printf("前序遍历为:");
	Preorder(cur);
	printf("\n中序遍历为:");
	Inorder(cur);
	printf("\n后序遍历为:");
    Postorder(cur);
	if(LeftNode(cur, 'C') != NULL)
		printf("\nC的左孩子为:%c",	LeftNode(cur, 'C')->data);
	if(RightNode(cur, 'C') != NULL)
		printf("\nC的右孩子为:%c",RightNode(cur, 'C')->data);
	if(ParentNode(cur, 'B'))
		printf("\nB的双亲为: %c", ParentNode(cur, 'B')->data);
	hight = BTreeHight(cur);
	printf("\n树的高度为:%d",hight);
    num = BTreeNum(cur);
	printf("\n树的节点个数为:%d", num);
	a = BTree(cur);
	printf("\n树的叶子节点为: %d", a);
	Knum = BTreeKnum(cur, 3);
	printf("\n树的第K层的节点数为: %d", Knum);
	Destroy(&cur);
	Destroy(&ret);
}

int main()
{
	Text();
	return 0;
}

二叉树的一些应用

BinTree.h

#ifndef _BINTREE_
#define _BINTREE_

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

typedef char DataType;

typedef struct BinTree
{
	DataType data;
	struct BinTree *left;
	struct BinTree *right;
}BinTree;

#define NUMBER 20


typedef struct Stack
{
	BinTree  a[NUMBER];
	int count;
}Stack;

typedef struct Node
{
	BinTree  data;
	struct Node*next;
}Node;


typedef struct Queue
{
	Node *Front;
	Node *Back;
}Queue;


void * InitBinTree(BinTree **q, DataType *str, int *i, int size);
void PreOrder(BinTree *q);
void InOrder(BinTree *q);
void PostOrder(BinTree *q);
int BinTreeHight(BinTree *q);
int BinTreeNodeNum(BinTree *q);
int BinTreeKNodeNum(BinTree *q, int K);
void BinTreeMirror(BinTree **q);
void PreOrderNor(BinTree *root, Stack *cur);
void InOrderNor(BinTree *root, Stack *cur);
void PostOrderNor(BinTree *root, Stack *cur);
void Order(BinTree *q);
int JudjeBinTree(BinTree *q);

#endif //_BINTREE

BinTree.c

#include"BinTree.h"

//创建一个节点
BinTree *BuyTreeNode(DataType d)
{
	BinTree* NewNode = (BinTree*)malloc(sizeof(BinTree));
	if(NewNode == NULL)
	{
		printf("申请失败\n");
		exit(0);
	}
	NewNode->data = d;
	NewNode->left = NULL;
	NewNode->right = NULL;
	return NewNode;
}

//创建一棵二叉树
//按照前序遍历的方法
void * InitBinTree(BinTree **q, DataType *str, int *i, int size)
{
	if(str[*i] != '#' && *i < size-1)
	{
		*q = BuyTreeNode(str[*i]);
		*i += 1;
		InitBinTree(&(*q)->left, str, i, size);
		*i += 1;
		InitBinTree(&(*q)->right, str, i, size);
	}
}
//前序遍历
void PreOrder(BinTree *q)
{
	if(NULL != q)
	{
		printf("%c ", (q)->data);
		PreOrder(q->left);
		PreOrder(q->right);
	}
}
//栈的初始化
void StackInit(Stack *ret)
{
	assert(ret);
	ret->count = 0;
}
//出栈
void StackPop(Stack **cur)
{
	assert(cur);
	if((*cur)->count == 0)
	{
		printf("栈空了\n");
		return ;
	}
	(*cur)->count--;
}
//入栈
void StackPush(Stack *cur, BinTree *data)
{
	assert(cur);
	(cur)->a[(cur)->count] = *data;
	(cur)->count++;
}
//取栈顶的元素
BinTree* StackTopNode(Stack *cur)
{
	assert(cur);
	return &cur->a[cur->count-1];
}
//判断栈是否为空
int EmptyStack(Stack* cur)
{
	assert(cur);
	if(cur->count == 0)
		return 1;
	return 0;
}
////前序非递归
//先遍历树的左子树,并将遍历过程中遇到的右节点保存到栈中
//当一次遍历的左子数为空时,再从栈中取栈顶的节点,以此节点为根节点,再次遍历它的左子数
//如此反复,直到栈为空时结束
void PreOrderNor(BinTree *root, Stack *cur)
{
	BinTree *ret = NULL;
	assert(root);
	StackInit(cur);
	StackPush(cur,root);

	while(!EmptyStack(cur))
	{
		ret = StackTopNode(cur);
		StackPop(&cur);
		while(ret != NULL)
		{
			BinTree *tmp = ret->right;
			printf("%c ", ret->data);
			ret = ret->left;
			if(tmp != NULL)
				StackPush(cur, tmp);	
		}
	}
}

//中序遍历
void InOrder(BinTree *q)
{
	if(NULL != q)
	{
		InOrder(q->left);
		printf("%c ", (q)->data);
		InOrder(q->right);
	}
}
//中序遍历非递归
//先寻找根节点下的最左边的节点,
void InOrderNor(BinTree *root, Stack *cur)
{
	BinTree *ret = NULL;
	assert(root);
	StackInit(cur);
	ret = root;
	while(!EmptyStack(cur) || NULL != ret)
	{
		while(ret)
		{
			StackPush(cur, ret);
			ret = ret->left;
		}
		ret = StackTopNode(cur);
		StackPop(&cur);
		printf("%c ", ret->data);
		ret = ret->right;
	}

}
//后序遍历
void PostOrder(BinTree *q)
{
	if(NULL != q)
	{
		PostOrder(q->left);
		PostOrder(q->right);
		printf("%c ", (q)->data);
	}
}
//后续的非递归遍历
//首先找到最左边的节点,然后查看此节点后没有右孩子,如果有的话再找右孩子的最左边的节点,如果没有的话,遍历
//做此节点,然后做标记,记录此节点已经遍历过,重复操作,直到站空
//标记是防止重复遍历节点
void PostOrderNor(BinTree *root, Stack *cur)
{
	BinTree *ret = NULL;
	BinTree *last = NULL;//用来标记已经遍历过的节点
	assert(root);
	StackInit(cur);
	ret = root;
	while(!EmptyStack(cur) || ret)
	{

		BinTree *top = 0;
		//找根节点下的最左边的节点
		while(ret)
		{
			StackPush(cur, ret);
			ret = ret->left;
		}
		//取出栈顶的元素
		top = StackTopNode(cur);
		//查看栈顶的元素是否为空,并且是否被遍历过,如果都没有的话,遍历该节点,并且更新标记
		if((top->right == NULL)||(top->right->data == last->data))
		{
			printf("%c ",top->data);
			last = top;
			StackPop(&cur);
		}
		//如果右右孩子的话,将根节点改为该节点的右节点,并且更新标记
		else
		{
			ret = top->right;
			last = top->right;
		}
	}
}

Node *BuyQueueNode(BinTree d)
{
	Node* NewNode = (Node*)malloc(sizeof(Node));
	if(NewNode == NULL)
	{
		printf("申请失败\n");
		exit(0);
	}
	NewNode->data = d;
	NewNode->next = NULL;
	return NewNode;
}
//入队列
void QueuePush(Queue *q, BinTree d)
{
	assert(q);
	if(q->Front == NULL)
	{
		q->Front = BuyQueueNode(d);
		q->Back = q->Front;
	}
	else
	{
		q->Back->next = BuyQueueNode(d);
		q->Back = q->Back->next;
	}
}
//出队列
void QueuePop(Queue*q)
{
	assert(q);
	if(q->Front != q->Back)
	{
		Node*ret = q->Front;
		q->Front = q->Front->next;
		free(ret);
		ret = NULL;
	}
	else
	{
		Node*ret = q->Front;
		free(ret);
		ret = NULL;
		q->Front = NULL;
		q->Back = NULL;
	}
}
DataType QueueEmpty(Queue*q)
{
	if(q->Front == NULL || q->Back == NULL)
		return 1;
	return 0;
}
//队头元素
BinTree QueueTopNode(Queue *q)
{
	return q->Front->data;
}
//队尾元素
BinTree QueueLaterNode(Queue *q)
{
	return q->Back->data;
}
//初始化队列
void QueueInit(Queue *q)
{
	assert(q);
	q->Back = NULL;
	q->Front = NULL;
}
//层序遍历
//取出队头的元素,并遍历
//如果该元素的孩子存在的话,左右孩子入栈
//重复上面的操作,直到队列空为止
void Order(BinTree *q)
{
	Queue cur = {0};
	BinTree ret = {0};
	BinTree *p = q;
	QueueInit(&cur);
	//将根节点入栈,刚开始队列为空
	QueuePush(&cur,*q);
	while(QueueEmpty(&cur) != 1)
	{
		ret = QueueTopNode(&cur);
		QueuePop(&cur);
		printf("%c ", ret);
		//左孩子存在的话,入队列
		if(ret.left != NULL)
			QueuePush(&cur, *(ret.left));
		//有孩子存在的话,入队列
		if(ret.right != NULL)
			QueuePush(&cur, *(ret.right));
	}
}
//判断一棵二叉树是不是完全二叉树
//如果是完全二叉树的话,一定不会有一个节点,只有右孩子而没有左孩子
//假设有一个节点只有左孩子而没有右孩子的
int JudjeBinTree(BinTree *q)
{
	Queue cur = {0};
	BinTree ret = {0};
	BinTree *p = q;
	QueueInit(&cur);
	QueuePush(&cur,*q);
	while(QueueEmpty(&cur) != 1)
	{
		ret = QueueTopNode(&cur);
		QueuePop(&cur);
		//当遇到的一个节点的左右孩子都为空时,退出循环,检查剩下的节点的孩子是否为空,如果有不为空的话,代表不是完全二叉树
		if(ret.left == NULL && ret.right == NULL)
		{
			break;
		}
		//当一个节点只有有孩子而没有左孩子时,一定不是完全二叉树
		if(ret.left == NULL && ret.right != NULL)
		{
			return 0;
		}
		//当一个节点的左孩子不为空而右孩子为空时,此节点后面的节点的孩子都不能为空
		if(ret.left != NULL && ret.right == NULL)
		{
			QueuePush(&cur, *(ret.left));
			break;
		}
		printf("%c ", ret);
		if(ret.left != NULL)
			QueuePush(&cur, *(ret.left));
		if(ret.right != NULL)
			QueuePush(&cur, *(ret.right));
	}
	//检查剩下的节点的孩子是否为空,不为空的话,不是完全二叉树
	if(!QueueEmpty(&cur))
	{
		ret = QueueTopNode(&cur);
		QueuePop(&cur);
		if(ret.left != NULL || ret.right != NULL)
			return 0;
	}
	return 1;
}

//树的高度
int BinTreeHight(BinTree *q)
{
	if(q == NULL)
		return 0;
	if(q->left == NULL && q->right == NULL)
		return 1;
	return BinTreeHight(q->left) > BinTreeHight(q->right) ? BinTreeHight(q->left)+1 : BinTreeHight(q->right)+1;
}
//求树中节点的个数
int BinTreeNodeNum(BinTree *q)
{
	if(q == NULL)
		return 0;
	return BinTreeNodeNum(q->left) + BinTreeNodeNum(q->right)+1;
}
//求二叉树中第K层节点的个数
int BinTreeKNodeNum(BinTree *q, int K)
{
	if(q == NULL)
		return 0;
	if(K == 1)
		return 1;
	return BinTreeKNodeNum(q->left, K-1) + BinTreeKNodeNum(q->right, K-1);
}
//判断一个节点是否在二叉树中
int FindNodeInBTree(BinTree *q, BinTree *pos)
{
	if(q == NULL || pos == NULL)
		return 0;
	if(q == pos)
		return 1;
	return FindNodeInBTree(q->left,pos) + FindNodeInBTree(q->right, pos);
}


//交换两个指针域
void Swap(BinTree **cur, BinTree **ret)
{
	BinTree *tmp = NULL;
	assert(cur && ret);
	tmp = *cur;
	*cur = *ret;
	*ret = tmp;
}

//求二叉树的镜像
void BinTreeMirror(BinTree **q)
{
	if(*q != NULL)
	{
		Swap(&(*q)->left,&(*q)->right);
		BinTreeMirror(&(*q)->left);
		BinTreeMirror(&(*q)->right);
	}
}

Main.c

#include"BinTree.h"

void Text()
{
	int  i = 0;
	BinTree *q = NULL;
	Stack cur = {0};
	DataType str[] = "ABD###CE##F";
	InitBinTree(&q, str, &i, sizeof(str)/sizeof(str[0]));
	printf("前序遍历为:");
	PreOrder(q);
	printf("\n中序遍历为:");
	InOrder(q);
	printf("\n后序遍历为:");
	PostOrder(q);
	i = BinTreeHight(q);
	i = BinTreeNodeNum(q);
	i = BinTreeKNodeNum(q, 3);
	//BinTreeMirror(&q);
	printf("\n前序遍历为:");
	PreOrderNor(q, &cur);
	printf("\n中序遍历为:");
	InOrderNor(q, &cur);
	printf("\n后序遍历为:");
	PostOrderNor(q, &cur);
	printf("\n层序遍历为:");
	Order(q);
	i = JudjeBinTree(q);
}

int main()
{
	Text();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Ksaila/article/details/82631813