二叉树的基本操作及面试题

bintree.h

#pragma once

#include <stdio.h>
typedef char BDataType;
typedef struct BinTreeNode
{
	//struct BinTreeNode* _pParent;  //  指向当前节点的双亲
	struct BinTreeNode* _pLeft; //  指向当前节点左孩子
	struct BinTreeNode* _pRight; //  指向当前节点右孩子
	BDataType _data; //  当前节点值域
}BtRoot,*pBTNode;

//二叉树的创建
void bintree_create(pBTNode* tRoot,BDataType array[]);

//节点的创建
pBTNode bintreenode_create(BDataType data);

//遍历二叉树---前序(递归)
void PreOrder_D(pBTNode tRoot);

//遍历二叉树---前序(非递归)
void PreOrder_FD(pBTNode tRoot);

//遍历二叉树---中序(递归)
void MidOrder_D(pBTNode tRoot);

//遍历二叉树---中序(非递归)
void MidOrder_FD(pBTNode tRoot);

//遍历二叉树---后序(递归)
void PostOrder_D(pBTNode tRoot);

//遍历二叉树---后序(非递归)
void PostOrder_FD(pBTNode tRoot);

//层序遍历
void Levelorder(pBTNode tRoot);

//非递归遍历
//栈--前序遍历


//二叉树的复制
pBTNode Copy_bintree(pBTNode tRoot);

//镜像二叉树--非递归(层序)
void MirrorBinTree_FD(pBTNode* tRoot);

//镜像二叉树---递归(前序)
void MirrorBinTree_D(pBTNode* tRoot);

//交换节点
void swapNode(pBTNode* pLeft,pBTNode* pRight);

//二叉树节点个数
int BinTreeSize(pBTNode tRoot);

//二叉树的深度
int BinTreeDepth(pBTNode pRoot);

//求第k层的节点个数
int GetKLevelNode(pBTNode pRoot,int k);

// 二叉树的销毁 
void DetroyBinTree(pBTNode* pRoot);

// 在二叉树中查找值为data的结点,找到返回该结点,否则返回空 
pBTNode Find(pBTNode pRoot, BDataType data); 

//找是否存在一个节点在二叉树中
int IsNodeInBinTree(pBTNode pRoot,pBTNode data);

//判断是否是完全二叉树
int IsCompleteBinTree(pBTNode pRoot);

1.二叉树的创建---采用递归的方法,创建根+左子树+右子树。

void bintree_create(pBTNode* tRoot,BDataType array[])
{
       int index=0;
       _bintree_create(tRoot,array,&index);
}

void _bintree_create(pBTNode* tRoot,BDataType array[],int* index)
{
	assert(tRoot);
	if('*' != array[*index] && '#'!=array[*index])
	{
		//根节点的创建
		*tRoot=bintreenode_create(array[*index]);
		//左子树的创建
		++(*index);
		_bintree_create(&(*tRoot)->_pLeft,array,index);
		//右子树的创建
		++(*index);
		_bintree_create(&(*tRoot)->_pRight,array,index);
	}
}.

2.二叉树节点的创建。

pBTNode bintreenode_create(BDataType data)
{
    pBTNode pNewNode=NULL;
	pNewNode=(pBTNode)malloc(sizeof(BtRoot));
	if(NULL == pNewNode)
	{
		assert(pNewNode);
		return NULL;
	}
	pNewNode->_data=data;
	pNewNode->_pLeft=NULL;
	pNewNode->_pRight=NULL;
	return pNewNode;
}

3.二叉树的复制---同样是递归的方法

pBTNode Copy_bintree(pBTNode tRoot)
{
	pBTNode pNewNode=NULL;
    if(tRoot)
	{
      pNewNode=bintreenode_create(tRoot->_data);
	  Copy_bintree(tRoot->_pLeft);
	  Copy_bintree(tRoot->_pRight);
	}
    return pNewNode;
}

4.二叉树的遍历

(1)前序遍历---递归

void PreOrder_D(pBTNode tRoot)
{
	if(tRoot)
	{
		printf("%c ",tRoot->_data);
		PreOrder_D(tRoot->_pLeft);
		PreOrder_D(tRoot->_pRight);
	}
}

(2)前序遍历---非递归(两种方法)

void PreOrder_FD(pBTNode tRoot)
{
#if 0
	pLstack s;
	pBTNode pCur=NULL;
	LstackInit(&s);
	LstackPush(&s,tRoot);
	if(NULL == tRoot)
		return;
	while (!LstackEmpty(s))
	{
		pCur=s->_data;      //取栈顶
		printf("%c ",pCur->_data);
		LstackPop(&s);                   //出栈
		if(pCur->_pRight)
			LstackPush(&s,pCur->_pRight);
		if(pCur->_pLeft)
			LstackPush(&s,pCur->_pLeft);
	}
#endif

	pLstack s;
	pBTNode pCur=NULL;
	LstackInit(&s);
	LstackPush(&s,tRoot);
	if(NULL == tRoot)
		return;
    while (!LstackEmpty(s))
    {
	   pCur=s->_data;
	   LstackPop(&s);
       while (pCur)
       {
		   printf("%c ",pCur->_data);
		   if(pCur->_pRight)
			   LstackPush(&s,pCur->_pRight);
		   pCur=pCur->_pLeft;
       }
    }
    printf("\n");
}

(3)中序遍历---递归

void MidOrder_D(pBTNode tRoot)
{
	if(tRoot)
	{
		MidOrder_D(tRoot->_pLeft);
	    printf("%c ",tRoot->_data);
		MidOrder_D(tRoot->_pRight);
	}
}

(4)中序遍历---非递归:需要用到栈(此处用的是链栈)先找到最左下角的节点,然后访问当前节点,出栈,访问当前节点的右节点。

void MidOrder_FD(pBTNode tRoot)
{
   pLstack s;
   pBTNode pCur=tRoot;
   LstackInit(&s);
   if(NULL == tRoot)
	   return;
   while (pCur || (!LstackEmpty(s)))
   {
	   while (pCur)
	   {
		 LstackPush(&s,pCur);
		 pCur=pCur->_pLeft;
	   }
	   pCur=s->_data;
	   printf("%c ",pCur->_data);
	   LstackPop(&s);
	   pCur=pCur->_pRight;
   }
   printf("\n");
}

(5)后序遍历---递归

void PostOrder_D(pBTNode tRoot)
{
	if(tRoot)
	{
		PostOrder_D(tRoot->_pLeft);
		PostOrder_D(tRoot->_pRight);
		printf("%c ",tRoot->_data);
	}
}
(6)后序遍历---非递归:需用到链栈,先找到最左下角的节点,并访问;然后判断,如果当前节点的右节点为空,或者右节点已经访问过了。就访问当前节点,否则向当前节点的右节点走。 
void PostOrder_FD(pBTNode tRoot)
{
	pLstack s;
	pBTNode pCur=tRoot,pMark=NULL,pTop=NULL;
	LstackInit(&s);
    if(NULL == tRoot)
		return;
    while (pCur || (!LstackEmpty(s)))
    {
		while (pCur)
		{        
                        LstackPush(&s,pCur);
	 		pCur=pCur->_pLeft;
		}
		pTop=s->_data;    //取栈顶
        if(NULL == pTop->_pRight || pTop->_pRight==pMark)
		{
			printf("%c ",pTop->_data);
			pMark=pTop;
		    LstackPop(&s);
		}
		else
			pCur=pTop->_pRight;
    }
	printf("\n");
}

(7)层序遍历:需用到队列(先进先出),根入队列,访问当前节点,然后左子树入队列,接着右子树入队列,循环。

void Levelorder(pBTNode tRoot)
{
	Queue q;
	pBTNode pCur=NULL;
    if(NULL==tRoot)
	   return;
	QueueInit(&q);
    QPush(&q,tRoot);
	while (!QueueEmpty(q))
	{
		pCur=Qfront(q);
		QPop(&q);
		printf("%c ",pCur->_data);
		if(pCur->_pLeft)
			QPush(&q,pCur->_pLeft);
		if(pCur->_pRight)
			QPush(&q,pCur->_pRight);
	}
}
5.镜像二叉树
//镜像二叉树--非递归(层序)
void MirrorBinTree_FD(pBTNode* tRoot)
{
	Queue q;
	pBTNode pCur=NULL;
	if(NULL==tRoot)
	{
		assert(tRoot);
		return;
	}
	QueueInit(&q);
	QPush(&q,*tRoot);
	while (!QueueEmpty(q))
	{
		pCur=Qfront(q);
		QPop(&q);
		swapNode(&(pCur->_pLeft),&(pCur->_pRight));
		if(pCur->_pLeft)
			QPush(&q,pCur->_pLeft);
		if(pCur->_pRight)
			QPush(&q,pCur->_pRight);
	}
}
//交换节点
void swapNode(pBTNode* pLeft,pBTNode* pRight)
{
     pBTNode tmp=NULL;
	 tmp=*pLeft;
     *pLeft=*pRight;
	 *pRight=tmp;
}

//镜像二叉树---递归(前序)
void MirrorBinTree_D(pBTNode* tRoot)
{
	if(*tRoot)
	{
		swapNode(&((*tRoot)->_pLeft),&((*tRoot)->_pRight));
		MirrorBinTree_FD(&((*tRoot)->_pLeft));
		MirrorBinTree_FD(&((*tRoot)->_pRight));
	}
}

6.//判断是否是完全二叉树:即如果是完全二叉树,只会出现一个“临界”节点(只有左节点,只有右节点或者无子节点),此时将标记flag置为1。当函数结束时,flag为1表示是完全二叉树,否则不是。

int IsCompleteBinTree(pBTNode pRoot)
{
	Queue q;
	pBTNode cur=NULL;
	int flag=0;
	if(NULL == pRoot)
		return 0;
	QueueInit(&q);
	QPush(&q,pRoot);
	while (!QueueEmpty(q))
	{
       cur=Qfront(q);
	   if(1==flag && (cur->_pLeft || cur->_pRight))
		   return 0;
	   if(cur->_pLeft && cur->_pRight)     //左右子树均存在
	   {
		   QPush(&q,cur->_pLeft);            //左子树入栈
		   QPush(&q,cur->_pRight);           //右子树入栈
	   } 
	   else if(cur->_pLeft)                 //仅左子树存在
	   {
		   QPush(&q,cur->_pLeft); 
		   flag=1;
	   }
	   else if(cur->_pRight)                //仅右子树存在
	   {
           QPush(&q,cur->_pRight);
		   flag=1;
	   }
	   else                      //当前节点无子树                         
		   flag=1;
	   QPop(&q);
	}
	return 1;
}

7.其他基本操作

//二叉树节点个数
int BinTreeSize(pBTNode tRoot)
{
   if(NULL == tRoot)
	   return 0;
   return 1+BinTreeSize(tRoot->_pLeft)+BinTreeSize(tRoot->_pRight);
}

//二叉树的深度
int BinTreeDepth(pBTNode pRoot)
{
	int Dleft=0,Dright=0;
	if(NULL == pRoot)
		return 0;
	Dleft=BinTreeDepth(pRoot->_pLeft);
	Dleft=BinTreeDepth(pRoot->_pRight);
	return Dleft>Dright?(Dleft+1):(Dright+1);
}

//求第k层的节点个数
int GetKLevelNode(pBTNode pRoot,int k)
{
	if(NULL == pRoot)
		return 0;
	if( 1== k)
		return 1;
	return GetKLevelNode(pRoot->_pLeft,k-1)+GetKLevelNode(pRoot->_pRight,k-1);
}

// 二叉树的销毁 
void DetroyBinTree(pBTNode* pRoot)
{
	if(NULL == (*pRoot))
		return;
	if((*pRoot)->_pLeft)
		DetroyBinTree(&((*pRoot)->_pLeft));
	if((*pRoot)->_pRight)
		DetroyBinTree(&((*pRoot)->_pRight));
	free(*pRoot);
}

// 在二叉树中查找值为data的结点,找到返回该结点,否则返回空 
pBTNode Find(pBTNode pRoot, BDataType data)
{
	pBTNode pCur=NULL;
	Queue q;
	QueueInit(&q);
    if(NULL == pRoot)
		  return NULL;
    pCur=pRoot;
    QPush(&q,pCur);
	while (!QueueEmpty(q))
	{
		pCur=Qfront(q);
		if(data==pCur->_data)
			return pCur;
		if(pCur->_pLeft)
			QPush(&q,pCur->_pLeft);
		if(pCur->_pRight)
			QPush(&q,pCur->_pRight);
		QPop(&q);
	}
	printf("没找到\n");
	return NULL;
}

//找是否存在一个节点在二叉树中
int IsNodeInBinTree(pBTNode pRoot,pBTNode pNode)
{
     if(NULL== pRoot)
		 return 0;
	 if(pNode==pRoot)
		 return 1;
	 if(IsNodeInBinTree(pRoot->_pLeft,pNode))
		 return 1;
	 if(IsNodeInBinTree(pRoot->_pRight,pNode))
		 return 1;
	 return 0;
}

test.c

#include "bintree.h"
#include "Linkstack.h"
int main()
{
	pBTNode bintree,pNewNode;
	char array[]="ABC###DE##F**";
	bintree_create(&bintree,array);
	//前序遍历
	printf("前序遍历\n");
	PreOrder_D(bintree);
	printf("\n");
    PreOrder_FD(bintree);
	printf("中序遍历\n");
	MidOrder_D(bintree);
	printf("\n");
	MidOrder_FD(bintree);
	printf("后序遍历\n");
	PostOrder_D(bintree);
	printf("\n");
	PostOrder_FD(bintree);
	//pNewNode=Copy_bintree(bintree);
    //PreOrder_D(bintree);
	//层序遍历
	//Levelorder(bintree);
	//镜像二叉树-递归
	//MirrorBinTree_D(&bintree);
	//镜像二叉树-递归
    MirrorBinTree_FD(&bintree);
	PreOrder_D(bintree);
	//Levelorder(bintree);
	printf("大小 = %d\n",BinTreeSize(bintree));
	printf("深度 = %d\n",BinTreeDepth(bintree));
	if(IsCompleteBinTree(bintree))
		printf("是完全二叉树\n");
	else
		printf("不是完全二叉树\n");
	//求第k层节点个数
	printf("%d\n",GetKLevelNode(bintree,1));
    pNewNode=Find(bintree,'F');
	if(IsNodeInBinTree(bintree,pNewNode))
		printf("找到了\n");
	else
		printf("没找到\n");
	DetroyBinTree(&bintree);
	return 0;
}




猜你喜欢

转载自blog.csdn.net/qq_33279168/article/details/80186539