二叉树的图示
下图便是一个普通的二叉树
下图是一个满二叉树
下图是一个完全二叉树
注意:完全二叉树的元素,最后一层右边可以没有元素,但紧挨着的左边一定是满元素的
二叉树的相关概念
我们接下来以一个普通的二叉树来讲解二叉树的相关概 吧念
根节点:同链表中的头节点,也就是第一个元素,即上图的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;
}