C语言_二叉树的基本操作及常见面试题

本片博客主要包含以下内容:

和二叉树操作相关的队列基本操作

初始化
入队列
判断队列是否为空
出队列,返回对头元素

和二叉树相关的栈的基本操作

初始化
入栈
出栈
判空
返回栈顶元素并出栈
返回栈顶元素不出栈

二叉树操作

创建新节点
创建树
前序遍历(递归)
前序遍历(非递归)
中序遍历(递归)
中序遍历(非递归)
后序遍历(递归)
后序遍历(非递归)
层序遍历
求树的高度
求叶子节点的个数
求二叉树节点的个数
求第k层的节点个数
求一个节点的双亲结点
获取一个节点的左孩子结点
求一个节点的左孩子节点
获取一个节点的右孩子结点
求二叉树的镜像(递归)
求二叉树的镜像(非递归)

#1、队列操作

//初始化队列
void InitStatus (Status *Sta)	
{
	assert (Sta != NULL);
	Sta->rear = 0;
	Sta->front = 0;
}
//入队列
void PushStatus (Status *sta, pBTNode data)	
{
	assert (sta);
	if (sta->rear == MAX_SIZE)
	{
		printf ("队列已满,无法入队列!!!\n");
		return;
	}
	sta->data[sta->rear] = data;
	sta->rear++;
}
//出队列,返回对头元素
pBTNode PopStatus(Status *sta)	
{
	int i = 0;
	pBTNode ch;
	assert (sta != NULL);
	if (sta->rear == 0)
	{
		printf ("队列为空!!!\n");
		return NULL;
	}
	ch = sta->data[0];
	for (i = 0; i<sta->rear-1; ++i)
	{
		sta->data[i] = sta->data[i+1];
	}
	sta->rear --;
	return ch;
}
//判断队列是否为空
int IsEmpty_Status (Status *sta)	
{
	return sta->rear==0;
}

#2、栈的操作

void InitStack (Stack *p)	//初始化
{
	assert (p != NULL);
	p->top = 0;
}

void PushStack (Stack *p, pBTNode d)	//入栈
{
	assert (p);
	if (p->top == MAXSIZE)
	{
		printf ("栈满,无法入栈!!!\n");
		return;
	}
	p->data[p->top++] = d;
}

void PopStack (Stack *p)//出栈
{
	assert (p);
	if (p->top == 0)
	{
		printf ("栈空,操作失败!!!\n");
		return;
	}
	p->top --;
}

int IsStaticEmpty (Stack *p)	// 判空
{
	return (p->top == 0);//如果为空,返回1;如果不为空,返回0
}

pBTNode TopNumAndTop (Stack *p)	 //返回栈顶元素(出栈)
{
	if (p->top == 0)
	{
		printf ("栈为空!!\n");
		return 0;
	}
	return p->data[--(p->top)];
}

pBTNode TopNum (Stack *p)	//返回栈顶元素(不出栈)
{
	if (p->top == 0)
	{
		printf ("栈为空!!\n");
		return 0;
	}
	return p->data[(p->top)-1];

}

#3、二叉树操作

##(1)创建新节点

pBTNode BuyNode (DataType d)
{
	pBTNode node = (pBTNode) malloc (sizeof (BTNode));
	if (NULL == node)
	{
		perror ("BuyNode :: malloc>>");
		return NULL;
	}
	node->d = d;
	node->_pLeft = NULL;
	node->_pRight = NULL;
	return node;
}

##(2)建树

void Create_Tree(BTNode **pRoot, DataType* arr, int len, int* count)
{
	assert (pRoot);
	assert (arr);

	if (*count < len && arr[*count] != '#')
	{
		(*pRoot) = BuyNode (arr[*count]);	//创建根节点

		(*count)++;
		Create_Tree(&(*pRoot)->_pLeft, arr, len, count);		//创建左子树

		(*count)++;
		Create_Tree(&(*pRoot)->_pRight, arr, len, count);	//创建右子树
	}
}

##(3)二叉树前序递归遍历

//前序(递归):根节点 --> 左子树 --> 右子树
void PreOrder (BTNode *pRoot)
{
	if (pRoot != NULL)
	{
		// 遍历更节点
		printf ("%c ", pRoot->d);
		//左子树
		PreOrder (pRoot->_pLeft);
		//右子树
		PreOrder (pRoot->_pRight);
	}
}

##(4)、二叉树前序非递归遍历

//先遍历根节点,如果根节点的左子树不为空,在遍历左子树的更节点,如果根节点的右子树不为空,右子树更节点入栈
//当左子树为空时,栈顶元素出栈,在以栈顶元素作为根节点
//直到栈为空
void PreOrderNoR(BTNode* pRoot)	//前序遍历(非递归)
{
	BTNode* cur = NULL;
	Stack s;
	if (pRoot == NULL)
	{
		printf ("树为空!!!\n");
		return;
	}
	//树不为空
	InitStack(&s);
	printf ("%c ", pRoot->d);
	cur = pRoot->_pLeft;
	if (pRoot->_pRight != NULL)
	{
		PushStack(&s, pRoot->_pRight);
	}
	while (!IsStaticEmpty(&s) || cur != NULL)
	{
		
		while (cur != NULL)
		{
			if (cur->_pRight != NULL)
			{
				PushStack(&s, cur->_pRight);
			}
			printf ("%c ", cur->d);
			cur = cur->_pLeft;
		}
		if (!IsStaticEmpty(&s))
			cur = TopNumAndTop(&s);
	}
}

##(5)二叉树中序递归遍历

//中序(递归):左子树--> 根节点--> 右子树
void InOrder (BTNode *pRoot)
{
	if (pRoot != NULL)
	{
		InOrder (pRoot->_pLeft);
		printf ("%c ", pRoot->d);
		InOrder (pRoot->_pRight);
	}
}

##(6)二叉树中序非递归遍历

//中序非递归遍历
//先找到最左边的节点
void InOrderNor(BTNode* pRoot)
{
	BTNode* cur = NULL;
	Stack s;
	if (pRoot == NULL)
	{
		printf ("树为空!!!\n");
		return ;
	}
	//树不为空
	InitStack(&s);
	cur = pRoot;

	while (!IsStaticEmpty(&s) || cur)
	{
		while (cur)
		{
			PushStack(&s, cur);
			cur = cur->_pLeft;
		}
		cur = TopNumAndTop(&s);
		printf ("%c ", cur->d);

		cur = cur->_pRight;

	}
	
}

##(7)二叉树后序递归遍历

//后序(递归): 左子树--> 右子树 --> 根节点
void PostOrder (BTNode *pRoot)	//后序遍历(递归)
{
	if (pRoot != NULL)
	{
		PostOrder (pRoot->_pLeft);
		PostOrder (pRoot->_pRight);
		printf ("%c ", pRoot->d);
	}
}

##(8)二叉树后序非递归遍历

void PostOrderNoR (BTNode *pRoot)	//后序遍历(非递归)
{
	Stack s;
	BTNode* cur = NULL;
	BTNode* mask = NULL;// 用来标记已经遍历过得节点
	if (pRoot == NULL)
	{
		printf ("树为空!!!\n");
		return;
	}
	InitStack(&s);
	cur = pRoot;
	//树不为空
	while (!IsStaticEmpty(&s) || cur)
	{
		BTNode* top = NULL;
		while (cur)	//找最左边的节点
		{
			PushStack(&s, cur);
			cur = cur->_pLeft;
		}
		top = TopNum(&s);

		//如果cur的右孩子为空或者已经被遍历过,则遍历该节点
		if (top->_pRight == NULL || top->_pRight->d == mask->d)
		{
			printf ("%c ", top->d);
			mask = top;	//刷新标记
			PopStack(&s);	//栈顶元素出栈
		}
		else	//如果右孩子不为空并且右孩子没有被遍历过,找右子树最左边的节点
		{
			cur = top->_pRight;
			mask = cur->_pRight;
		}
	}
}

##(9)层序遍历

void FloorOrder (BTNode *pRoot)
{
	Status sta;
	pBTNode proot;
	InitStatus (&sta);
	assert (pRoot != NULL);
	PushStatus (&sta, pRoot);//根节点入队列
	while (!IsEmpty_Status(&sta))
	{
		proot = PopStatus (&sta);
		printf ("%c ", proot->d);
		if (proot->_pLeft != NULL)
		{
			PushStatus (&sta, proot->_pLeft);
		}
		if (proot->_pRight != NULL)
		{
			PushStatus (&sta, proot->_pRight);
		}
	}
}

##(10)获取二叉树高度

int Max (int a, int b)
{
	return a>b?a:b;
}

int GetHeight (BTNode *pRoot)
{
	if (pRoot == NULL)
	{
		return 0;
	}
	else if (pRoot->_pLeft == NULL && pRoot->_pRight == NULL)
	{
		return 1;
	}
	else
	{
		return 1+ (Max (GetHeight (pRoot->_pLeft), GetHeight(pRoot->_pRight)));
	}
}

##(11)获取二叉树叶子节点数

int GetLeaf (BTNode *pRoot)
{
	if (NULL == pRoot)
	{
		return 0;
	}
	else if (pRoot->_pLeft == NULL && pRoot->_pRight == NULL)
	{
		return 1;
	}
	else
	{
		return GetLeaf(pRoot->_pLeft)+GetLeaf(pRoot->_pRight);
	}
}

##(12)求二叉树节点的个数

int GetNode (BTNode *pRoot)	//求二叉树节点的个数
{
	if (NULL == pRoot)
	{
		return 0;
	}
	else if ( NULL == pRoot->_pLeft && NULL == pRoot->_pRight )
	{
		return 1;
	}
	else
	{
		return GetNode (pRoot->_pLeft)+GetNode (pRoot->_pRight)+1;
	}
}

##(13)求二叉树节点个数

int GetKNode (BTNode* pRoot, int k, int high)
{
	if (k <= 0 || k > high || pRoot == NULL)	//如果k小于等于零,或者k大于树的高度,或者树为空
		return 0;
	else if (k == 1)
	{
		return 1;
	}
	else
	{
		return (GetKNode (pRoot->_pLeft , k-1, high) + GetKNode (pRoot->_pRight, k-1, high));
	}
}

##(14)求二叉树中一个节点的双亲节点

pBTNode GetParent(BTNode* pRoot, DataType data)	//求一个节点的双亲结点
{
	BTNode *root = pRoot;
	assert (pRoot != NULL);
	if (root->d == data)
	{
		return NULL;
	}
	if (pRoot->_pLeft != NULL || pRoot->_pRight != NULL)
	{
		if (pRoot->_pLeft->d == data || pRoot->_pRight->d == data)
			return pRoot;
		else
		{
			return GetParent (pRoot->_pLeft, data);
			return GetParent (pRoot->_pRight, data);
		}
	}
	return NULL;
}

##(15)递归求一个节点的左孩子


//递归求一个节点的左孩子
pBTNode LeftNode(pBTNode cur, DataType  data)
{
	BTNode *ret = NULL;
	if(NULL == cur)
		return NULL;
	if(cur->d == data && cur->_pLeft != NULL)
	{
		return cur->_pLeft;
	}
	ret = LeftNode(cur->_pLeft, data);
	if(NULL == ret)
	{
		ret = LeftNode(cur->_pRight, data);
	}
	return ret;
}

##(16)求一个节点的左孩子结点

pBTNode GetLeftChild (BTNode* pRoot, DataType data)	//获取一个节点的左孩子结点
{
	BTNode *cur = NULL;
	Status sta; //队列
	InitStatus (&sta);
	assert (pRoot != NULL);
	cur = pRoot;
	PushStatus (&sta, cur);//头节点入队列
	while (!IsEmpty_Status (&sta) && cur)
	{
		cur = PopStatus (&sta);
		if (cur->d == data)
		{
			return cur->_pLeft;
		}
		if (cur->_pLeft != NULL)//若左子树不为空,左子树头节点入队列
		{
			PushStatus (&sta, cur->_pLeft);
		}
		if (cur->_pRight != NULL)//若右子树不为空,右子树头节点入队列
		{
			PushStatus (&sta, cur->_pRight);
		}
	}
	return NULL;
}

##(17)求一个节点的右孩子结点

pBTNode GetRightChild (BTNode* pRoot, DataType data)	//获取一个节点的右孩子结点
{
	BTNode *cur = NULL;
	Status sta; //队列
	InitStatus (&sta);
	assert (pRoot != NULL);
	cur = pRoot;
	PushStatus (&sta, cur);//头节点入队列
	while (!IsEmpty_Status (&sta) && cur)
	{
		cur = PopStatus (&sta);
		if (cur->d == data)
		{
			return cur->_pRight;
		}
		if (cur->_pLeft != NULL)//若左子树不为空,左子树头节点入队列
		{
			PushStatus (&sta, cur->_pLeft);
		}
		if (cur->_pRight != NULL)//若右子树不为空,右子树头节点入队列
		{
			PushStatus (&sta, cur->_pRight);
		}
	}
	return NULL;
}

##(18)递归求二叉树的镜像

void swap (BTNode **a, BTNode **b)
{
	BTNode * tmp = *a;
	*a = *b;
	*b = tmp;
}

void BTreeMirrorR(BTNode *pRoot)// 求二叉树的镜像(递归)
{
	if (pRoot != NULL)
	{
		if (pRoot->_pLeft != NULL || pRoot->_pRight != NULL)
		{
			swap (&pRoot->_pLeft, &pRoot->_pRight);
			BTreeMirrorR(pRoot->_pLeft);	
			BTreeMirrorR(pRoot->_pRight);
		}
	}
}

##(19)非递归求二叉树的镜像

void BTreeMirrorNoR(BTNode *pRoot)// 求二叉树的镜像(非递归)
{
	Status s;
	BTNode* cur = NULL;
	InitStatus(&s);

	if (pRoot == NULL)
	{
		return NULL;
	}

	PushStatus (&s, pRoot);	//头结点入队列
	while ( !IsEmpty_Status (&s))
	{
		cur = PopStatus(&s);	//对头元素出队列并返回对头元素

		if (cur ->_pLeft != NULL )
		{
			PushStatus (&s, cur->_pLeft);	//左孩子不为空,左孩子入队列
		}
		if (cur->_pRight != NULL)
		{
			PushStatus(&s, cur->_pRight);	//右孩子不为空,右孩子入队列
		}
		swap (&cur->_pLeft, &cur->_pRight);
	}
}

头文件 包含以下内容 (BTree.h)

#ifndef __BTREE_H__
#define __BTREE_H__

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

#define MAX_SIZE 10	//队列
#define MAXSIZE 30	//栈

typedef char DataType;
/////////////////////////////////////////////////////////////////////////////////////////////
//二叉树
typedef struct BTNode
{
	struct BTNode* _pLeft;
	struct BTNode* _pRight;
	DataType d;

}BTNode, *pBTNode;

////////////////////////////////////////////////////////////////////////////////////////////
//队列

typedef struct Status
{
	int front;//对头
	int rear;//对尾
	pBTNode data[MAX_SIZE]; 
}Status;

//////////////////////////////////////////////////////////////////////////////////////////////
//栈

typedef struct STACK
{
	int top ;	//栈顶
	pBTNode data[MAXSIZE];	//数据
}Stack;


////////////////////////////////////////////////////////////////////////////////////////////
//队列操作
void InitStatus (Status *Sta);//初始化

void PushStatus (Status *sta, pBTNode data);//入队列

int IsEmpty_Status (Status *sta);//判断队列是否为空

pBTNode PopStatus(Status *sta);	//出队列,返回对头元素

//////////////////////////////////////////////////////////////////////////////////////////////
//栈操作
void InitStack (Stack *p);	//初始化

void PushStack (Stack *p, pBTNode d);	//入栈

void PopStack (Stack *p);	// 出栈

int IsStaticEmpty (Stack *p);	// 判空

pBTNode TopNumAndTop (Stack *p);	 //返回栈顶元素并出栈

pBTNode TopNum (Stack *p);	//返回栈顶元素不出栈


/////////////////////////////////////////////////////////////////////////////////////////////////
//二叉树操作
pBTNode BuyNode (DataType d);	//创建新节点
void Create_Tree(BTNode **pRoot, DataType* arr, int len, int* count);	//创建树
void PreOrder (BTNode *pRoot);	//前序遍历(递归)
void PreOrderNoR(BTNode* pRoot);	//前序遍历(非递归)
void InOrder (BTNode *pRoot);	//中序遍历(递归)
void InOrderNor(BTNode* pRoot);	//中序遍历(非递归)
void PostOrder (BTNode *pRoot);	//后序遍历(递归)
void PostOrderNoR (BTNode *pRoot);	//后序遍历(非递归)	//后序遍历(非递归)
void FloorOrder (BTNode *pRoot);//层序遍历
int GetHeight (BTNode *pRoot);	//求树的高度
int GetLeaf (BTNode *pRoot);	//求叶子节点的个数
int GetNode (BTNode *pRoot);	//求二叉树节点的个数
int GetKNode (BTNode* pRoot, int k, int high);	//求第k层的节点个数
pBTNode GetParent(BTNode* pRoot, DataType node);	//求一个节点的双亲结点
pBTNode GetLeftChild (BTNode* pRoot, DataType node);	//获取一个节点的左孩子结点
pBTNode LeftNode(pBTNode cur, DataType  data);	//求一个节点的左孩子节点
pBTNode GetRightChild (BTNode* pRoot, DataType data);	//获取一个节点的右孩子结点
void BTreeMirrorR(BTNode *Root);	// 求二叉树的镜像(递归)
void BTreeMirrorNoR(BTNode *Root);	// 求二叉树的镜像(非递归)

#endif

测试代码如下test.c:

#include "BTree.h"

void test_BTree()
{
	pBTNode pRoot = NULL;
	pBTNode ret = NULL;
	char arr[] = {"ABD###CE##F"};
	int index = 0;
	Create_Tree (&pRoot, arr, strlen(arr), &index);
	printf ("前序遍历(递归):\n");
	PreOrder (pRoot);
	printf ("\n");

	printf ("前序遍历(非递归):\n");
	PreOrderNoR (pRoot);
	printf ("\n");

	printf ("中序遍历(递归):\n");
	InOrder (pRoot);
	printf ("\n");

	printf ("中序遍历(非递归):\n");
	InOrderNor (pRoot);
	printf ("\n");

	printf ("后序遍历(递归):\n");
	PostOrder (pRoot);
	printf ("\n");

	printf ("后序遍历(非递归):\n");
	PostOrderNoR (pRoot);
	printf ("\n");

	printf ("层序遍历:\n");
	FloorOrder(pRoot);
	printf ("\n");

	printf ("树的高度为:%d\n", GetHeight(pRoot));
	printf ("叶子节点的个数为:%d\n", GetLeaf (pRoot));
	printf ("二叉树节点的个数为:%d\n", GetNode (pRoot));
	printf ("二叉树第2层节点个数为:%d\n", GetKNode (pRoot, 2, GetHeight(pRoot)));
	ret = GetParent (pRoot, 'B');
	if (ret != NULL)
	{
		printf ("B的双亲结点为:%c\n", ret->d);
	}

	ret = LeftNode(pRoot, 'C');
	if (ret != NULL)
	{
		printf ("C的左孩子为:%c\n", ret->d);
	}

	ret = GetRightChild (pRoot, 'A');
	if (ret != NULL) 
	{
		printf ("A的右孩子为:%c\n", ret->d);
	}
	printf ("递归求二叉树的镜像:\n");
	BTreeMirrorR(pRoot);
	InOrder (pRoot);
	printf ("\n");
	printf ("非递归求二叉树的镜像:\n");
	BTreeMirrorNoR(pRoot);
	InOrder (pRoot);
	printf ("\n");
}

	

void test_Status()
{
	Status Sta;
	InitStatus (&Sta);
}
int main ()
{
	test_BTree();
	test_Status();
	system ("pause");
	return 0;
}

测试结果:

这里写图片描述

猜你喜欢

转载自blog.csdn.net/A__B__C__/article/details/82715694