数据结构与算法(三)二叉树

二叉树的图示

下图便是一个普通的二叉树

下图是一个满二叉树

下图是一个完全二叉树

注意:完全二叉树的元素,最后一层右边可以没有元素,但紧挨着的左边一定是满元素的

二叉树的相关概念

我们接下来以一个普通的二叉树来讲解二叉树的相关概 吧念

根节点:同链表中的头节点,也就是第一个元素,即上图的A

父节点:相对于子节点讲,如上图的A便是B和C的父节点

子节点:相对于父节点讲,如上图B和C就是A的子节点

左子树:父节点的左子树,如上图B是A的左子树

右子树:父节点的右子树,如上图C是A的右子树

二叉树的高度:二叉树的层数,如上图一共有四层,那么该树的高度就是4

子树的高度:以二叉树的某节点为根节点,计算层数即该子树高度

二叉树的遍历

我们以下图为例进行讲解

接下来我们以GDM三个节点进行演示

前序遍历:根左右:G->D->M

中序遍历:左根右:D->G->M

后序遍历:左右根:D->M->D

现在我么以上图整个树进行演示:

注意:每当遍历到一个节点后,都要先把该节点作为根遍历完它整个子树

前序遍历:G->D->A->F->E->M->H->Z

中序遍历:A->D->E->F->G->H->M->Z

后序遍历:A->E->F->D->H->Z->M->G

一个简单的方法迅速获取遍历途径:

前序遍历:在每个元素的左边画一个圈,从根节点开始,绕着外圈画途径,按照经过左边圈的顺序依次作为前序遍历的先后顺序

中序遍历:在每个元素的下边画一个圈,从根节点开始,绕着外圈画途径,按照经过下边圈的顺序依次作为前序遍历的先后顺序

后序遍历:在每个元素的右边画一个圈,从根节点开始,绕着外圈画途径,按照经过右边圈的顺序依次作为前序遍历的先后顺序

搜索二叉树

搜索二叉树/二叉排序树的特点:

1.有很好的查询性能

2.有很好的新增和删除的性能

3.若左子树不空,则左子树上所有的节点的值均小于它根节点的值

4.若右子树不空,则左子树上所有的节点的值均大于它根节点的值

5.左右子树也分别是二叉排序树

搜索二叉树的删除:

情况一:叶字节点

1.删除该节点

2.将父节点(左或右)指针置NULL

情况二:只有一个子树

1.删除该节点

2.将父节点(左或右)指向子树

情况三:左右子树都要

1.用右子树最小的节点取代源节点

2.再递归删除最小的节点

作业

如下有一程序,二叉树记录了不同的怪物,现要求使用前序中序后序三种方法遍历这些怪的名称

#pragma once
#include <Windows.h>
#include<iostream>
class Monster
{
public:
	int ID;
	int Level;
	char Name[20];
public:
	Monster() {}
	Monster(int ID, int Level, const char* Name)
	{
		this->ID = ID;
		this->Level = Level;
		memcpy(&this->Name, Name, strlen(Name) + 1);
	}
};

template<class T>
class TreeNode {
public:
	T element;					//当前节点存储的数据		
	TreeNode<T>* pLeft;					//指向左子节点的指针		
	TreeNode<T>* pRight;					//指向右子节点的指针		

	TreeNode(T& ele)
	{
		//初始化Node节点
		memset(&element, 0, sizeof(TreeNode));
		//为元素赋值
		memcpy(&element, &ele, sizeof(T));
		pLeft = pRight = NULL;
	}
};

template<class T>
class BSortTree {
public:
	BSortTree();											//构造函数		
	~BSortTree();											//析构函数		
public:
	void InOrderTraverse(TreeNode<T>* pNode);				//中序遍历
	void PreOrderTraverse(TreeNode<T>* pNode);			//前序遍历		
	void PostOrderTraverse(TreeNode<T>* pNode);			//后序遍历		
	TreeNode<T>* GetRoot();								//返回根节点		
	int GetDepth(TreeNode<T>* pNode);					//返回某个节点的高度/深度
private:
	void Init();
	void Clear(TreeNode<T>* node);
private:
	TreeNode<T>* m_pRoot;					    		//根结点指针		
	int size;												//树中元素总个数		
};



template<class T>
BSortTree<T>::BSortTree()
{
	Init();
}
template<class T>
BSortTree<T>::~BSortTree() {

	Clear(m_pRoot);
}

template<class T>
void BSortTree<T>::Init()
{

	Monster m1(1, 1, "刺猬");
	Monster m2(2, 2, "野狼");
	Monster m3(3, 3, "野猪");
	Monster m4(4, 4, "士兵");
	Monster m5(5, 5, "火龙");
	Monster m6(6, 6, "独角兽");
	Monster m7(7, 7, "江湖大盗");
	TreeNode<Monster>* n1 = new TreeNode<Monster>(m1);
	TreeNode<Monster>* n2 = new TreeNode<Monster>(m2);
	TreeNode<Monster>* n3 = new TreeNode<Monster>(m3);
	TreeNode<Monster>* n4 = new TreeNode<Monster>(m4);
	TreeNode<Monster>* n5 = new TreeNode<Monster>(m5);
	TreeNode<Monster>* n6 = new TreeNode<Monster>(m6);
	TreeNode<Monster>* n7 = new TreeNode<Monster>(m7);
	m_pRoot = n5;
	n5->pLeft = n4;
	n5->pRight = n6;
	n4->pLeft = n1;
	n1->pRight = n2;
	n6->pLeft = n3;
	n3->pRight = n7;
	size = 7;
	/*
					5

				4		6

			1		  3

			  2		    7

	*/
}

template <class T>
void BSortTree<T>::Clear(TreeNode<T>* pNode) //使用后序遍历进行删除
{
	if (pNode != NULL)
	{
		Clear(pNode->pLeft);
		Clear(pNode->pRight);
		delete(pNode);
		pNode = NULL;
	}
}


template<class T>
TreeNode<T>* BSortTree<T>::GetRoot()
{
	return m_pRoot;
}
template<class T>
int BSortTree<T>::GetDepth(TreeNode<T>* pNode)
{
	/*
				5

			4		6

		1		  3

		  2		    7

	*/
	if (pNode == NULL)
	{
		return 0;
	}
	else
	{
		int m = GetDepth(pNode->pLeft);
		int n = GetDepth(pNode->pRight);
		return (m > n) ? (m + 1) : (n + 1);
	}
}


template <class T>
void BSortTree<T>::InOrderTraverse(TreeNode<T>* pNode) //中序遍历
{
	//中序遍历所有怪物,列出怪的名字			左 根 右	
		/*
					5

				4		6

			1		  3

			  2		    7

	*/
	if (pNode != NULL)
	{
		InOrderTraverse(pNode->pLeft);
		std::cout << "ID:" << pNode->element.ID << " Level:" << pNode->element.Level << " Name:" << pNode->element.Name << std::endl;
		InOrderTraverse(pNode->pRight);
	}
	
}
template<class T>
void BSortTree<T>::PreOrderTraverse(TreeNode<T>* pNode)
{
	//前序遍历所有怪物,列出怪的名字			根 左 右	
	/*
				5

			4		6

		1		  3

		  2		    7

	*/
	if (pNode != NULL)
	{
		std::cout << "ID:" << pNode->element.ID << " Level:" << pNode->element.Level << " Name:" << pNode->element.Name << std::endl;
		PreOrderTraverse(pNode->pLeft);
		PreOrderTraverse(pNode->pRight);
	}
}
template<class T>
void BSortTree<T>::PostOrderTraverse(TreeNode<T>* pNode)
{
	//后序遍历所有怪物,列出怪的名字			 左 右 根	
/*
			5

		4		6

	1		  3

	  2		    7

*/
	if (pNode != NULL)
	{
		PostOrderTraverse(pNode->pLeft);
		PostOrderTraverse(pNode->pRight);
		std::cout << "ID:" << pNode->element.ID << " Level:" << pNode->element.Level << " Name:" << pNode->element.Name << std::endl;
	}
}
int main(int argc, char* argv[])
{
	BSortTree<Monster>* p = new BSortTree<Monster>();
	int Depth = p->GetDepth(p->GetRoot());
	std::cout << Depth << std::endl;
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值