有关树二叉树的一些操作

近日准备找工作,看了数据结构相关内容,在这里总结一下二叉树的相关操作,以示勉励。有更好的实现算法,希望大家一起分享。

PS.今天早上同学收到华为offer,下午去签约了,我比他晚一天面试,希望明天能有好的运气。

闲话不多说,直接上代码。

#include <iostream>
#include <stdlib.h>
#include <queue>

#define TRUE 1
#define FALSE 0

using namespace std;


typedef int ElementType;//二叉树节点元素类型
/**
*二叉查找树节点定义
**/
struct TreeNode
{
	ElementType data;
	struct TreeNode *left;
	struct TreeNode *right;
};

typedef struct TreeNode* Tree;


 

以上是本文用到的一些宏定义以及树节点定义。本文所有函数都通过Visual Studio 2010测试。

 

1.

/**
*创建一棵空的树
**/
Tree CreateEmptyTree(void)
{
	Tree tree = (Tree)malloc(sizeof(struct TreeNode)); //这里动态分配了内存,一定要记得在某个地方释放内存,并置tree = NULL
	if(NULL==tree)
	{
		cout<<"Failed in Create Empty Tree"<<endl;
		return NULL;
	}
	tree->left = NULL;
	tree->right = NULL;
	return tree;
}


2.

/**
*往树中插入一个新元素,如果元素重复,则不插入
**/
Tree Insert(ElementType x,Tree tree)
{
	if(NULL==tree)  //判断树是否为空
	{
		tree = CreateEmptyTree();  //为空,创建树
		if(NULL == tree)
		{
			cout<<"Insert tree failed!"<<endl;
		}
		else
		{
			tree->data = x;        //将新元素插入新创建的空树
			//这一步个人觉得可有可无,以为在CreateEmptyTree()中已经设定这个节点的左右子节点为NULL了。
			tree->left = tree->right = NULL;
		}
	}
	else
	{
		if(x<tree->data)
			tree->left = Insert(x,tree->left);  //如果元素小于根节点,插入树的左边
		else if(x>tree->data)
			tree->right = Insert(x,tree->right);//如果元素大于根节点,插入树的右边
	}
	return tree;
}


 

3.

/**
*根据数组元素创建树
*这里创建的树为二叉查找树
*len为数据元素个数**/
Tree CreateTreeByArray(ElementType * pArr,int len)
{
	Tree tree = CreateEmptyTree();   //首先创建空树
	int i;
	if(tree!=NULL)
	{
		tree->data = pArr[0];        //将数组首元素作为树根,如果数组首元素比较小,那么所创建的树的深度就会比较大
	}
	
	for(i=1;i<len;i++)              //将数组元素一次插入树中
	{
		Insert(pArr[i],tree);
	}
	return tree;
}


4.这个函数不用多说了。

/**
*访问节点元素
**/
void visit(ElementType x)
{
 cout<<x<<" ";
}


5.

/**
*中序遍历树
**/
void inOrderTree(Tree tree)
{
	if(NULL!=tree)
	{
		inOrderTree(tree->left);
		visit(tree->data);         //中序遍历就是先遍历左子树,再打印节点元素,最有遍历右子树
		inOrderTree(tree->right);
	}
}
 

 6.前序编译就先打印根节点,然后在依次递归左右子树

/**
*前序遍历
**/
void prefixTree(Tree tree)
{
	if(NULL!=tree)
	{
		visit(tree->data);
		prefixTree(tree->left);
		prefixTree(tree->right);
	}
}

7.

/**
*后序遍历
**/
void postTree(Tree tree)
{
	if(NULL!=tree)
	{
		prefixTree(tree->left);
		prefixTree(tree->right);
		visit(tree->data);
	}
}


8.

/**
*按层遍历树,原理是借用队列,
**/
void OrderTree(Tree tree)
{
	queue<Tree> q;
	if(NULL!=tree)
	{
		q.push(tree);      //将树根节点进入队列
	}
	while(!q.empty())      //判断队列是否为空,不为空,去队列最前面的节点,这个节点可以找到它的左右子节点,然后分别将它的左右子节点进入队列
	{
		if(q.front()->left!=NULL)             //队列最前面的节点是否有左子结点
			q.push(q.front()->left);
		if(q.front()->right!=NULL)           //队列最前面的节点是否有右子结点
			q.push(q.front()->right);
		visit(q.front()->data);              //输出队列最前面的节点
		q.pop();                             //将队列最前面的节点一处队列
	}
}


9.从二叉查找树中找到最小节点,根据左子树所有节点都比右子树节点元素小的原理,先判断是否含有左子树,如果不含,那么节点就是最小元素,如果有左子树,那么就递归查找左子树中的最小元素

/**
*找到树中元素值最小的节点,返回该节点的指针
**/
Tree FindMin(Tree tree)
{
	if(NULL==tree)
		return NULL;
	else if(tree->left==NULL)
	{
		return tree;
	}
	else
	{
		return FindMin(tree->left);
	}
}

10.在二叉查找树中找到与元素x相同的节点,并返回该节点的指针

Tree FindFromTree(Tree tree,ElementType x)
{
	if(tree==NULL)
		return NULL;
	else if(tree->data==x)//如果相等,直接返回
		return tree;
	else if(x < tree->data)//如果比当前节点小,那么从左子树中查找
		return FindFromTree(tree->left,x);
	else if(x>tree->data)//如果比当前节点大,那么从右子树中查找
		return FindFromTree(tree->right,x);
}

 

11.

/**
*从树中删除与X相等的节点
*分两种情况:一,要删除的节点没有左右子树,二、含有子树
**/
Tree DeleteFromTree(ElementType X,Tree tree)
{
	Tree tmpCell;
	
	if(NULL==tree)
	{
		printf("Element %d not found\n",X);
	}
	else if(X < tree->data)                  //向左遍历找到要删除的节点
	{
		tree->left = DeleteFromTree(X,tree->left);
	}
	else if(X > tree->data)                 //向右遍历找到要删除的节点
	{
		tree->right = DeleteFromTree(X,tree->right);
	}
	/**
	*如果当前节点即为要删除的节点,且左子树和右子树都不为空时,找到右子树中的最小元素,
	*将该最小元素的值赋值给要删除的节点,即将要删除的节点转移动它的右子树的最小元素节点上,
	*最后该最小元素删除,指针指向的内存释放。
	**/
	else if(tree->left && tree->right)     
	{
		tmpCell = FindMin(tree->right);    //
		tree->data = tmpCell->data ;       //
		tree->right = DeleteFromTree(tree->data,tree->right);
	}
	else
	{
		tmpCell = tree;
		if(tree->left == NULL)
		{
			tree = tree->right;
		}
		else if(tree->right == NULL)
		{
			tree = tree->left;
		}
		free(tmpCell);
	}
	return tree;
}


12.这个函数在13年威创视讯的笔试卷子上出现过

/**
*求树的深度
**/
int Hight(Tree tree)
{
	if(tree==NULL)
		return -1;
	else
		return 1+ max(Hight(tree->left),Hight(tree->right));
}

13.countLeaf的返回值以参数形式返回,

/**
*求树的叶子节点数目
**/
void countLeaf(Tree tree,int *count)
{
	if(tree!=NULL)
	{
		if(tree->left!=NULL && tree->right!=NULL)
			(*count)++;
		countLeaf(tree->left,count);
		countLeaf(tree->right,count);
	}
}


14.先复制左右子树,在复制根节点,

/**
*树的复制
**/
Tree copyTree(Tree tree)
{
	Tree newRoot,leftTree,rightTree;
	if(tree==NULL)return NULL;
	//if(tree->left!=NULL)         //不能做这样的判断
	leftTree = copyTree(tree->left);
	//if(tree->right!=NULL)
	rightTree = copyTree(tree->right);

	newRoot = (Tree )malloc(sizeof(struct TreeNode));
	if(!newRoot)
	{
		return NULL;
	}
	newRoot->data = tree->data;
	newRoot->left = leftTree;
	newRoot->right = rightTree;
	return newRoot;
	
}


15.

/**
*删除树
**/
void DeleteTree(Tree tree)
{
	if(tree!=NULL)
	{
		DeleteTree(tree->left);
		DeleteTree(tree->right);
		free(tree);
	}
}

void clearTree(Tree &tree)
{
	DeleteTree(tree);
	tree=NULL;   //这行代码很重要的,如果不置为NULL,就容易产生野指针
}

16.统计二叉树中的元素个数,这里给出了两种方法,分别用不同的返回方式放回结果

/**
*二叉树元素个数
**/
void size(Tree tree,int *_size)
{
	if(tree!=NULL)
	{
		(*_size)++;
		size(tree->left,_size);
		size(tree->right,_size);
	}
}
int treeSize(Tree tree)
{
	int count = 0;
	if(tree==NULL)return 0;
	else
	{
		count = treeSize(tree->left) + treeSize(tree->right) + 1;
	}
	return count;
}



17.

/**
*判断一棵树是否为空
**/
int empty(Tree tree)
{
	if(treeSize(tree)==0)
		return TRUE;
	else
		return FALSE;
}


 

 





 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值