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

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;
}

测试结果:

这里写图片描述

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值