树的简介
一起探索二叉树
两种代码实现方式
树的简介
树是什么呢????
在我看来,树就是结点的有限集合,n个结点构成某种所谓的“家族关系”,就形成了树。
上述括号里面的数字均为结点的索引结点,括号外面的都为结点存储的数据。
树的一些相关概念:
1.孩子:就是子结点,可以说是某个结点的后代,比如说,上图中,1和2就是0的子结点。
2.双亲:比如说1就是8的父结点。
3。度:当前结点直接的孩子,比如说,0直接的子结点就是1和2,所以它的度为2.
4.叶子:终端结点,比如说,3,4,5,6结点均到底了,不能再下去了,到了终端,因此就是叶子。
5.根:非终端结点,上述,0,1,2都没到底,均为根。
6.深度:
结点深度:看它是第几代。
树的深度:看这个树有几代。
一起探索二叉树
二叉树是树的一种,就是每一个结点的度数都不大于2,最多有两个孩子。
二叉树有几种不同的遍历,都和根结点输出的顺序有关,其分别为
前序遍历:根结点->左结点->右结点
中序遍历:左结点->根结点->右结点
后序遍历:左结点->右结点->根结点
以下是我自己做的图形演示(稍微丑点了,别介意哈)
六、二叉树的性质:
1、若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2i-1个节点
2、若规定只有根节点的二叉树的深度为1,则深度为k的二叉树的最大节点数是2k-1
3、对任何一棵二叉树,如果其叶子节点个数为n0,度为2的非叶子节点个数为n2,则n0=n2+1
4、具有n个节点的完全二叉树的深度k为log2(n+1)向上取整
5、对于具有n个节点的完全二叉树,如果按照从上至下从左至右的顺序对所有结点从0开始编号,则对于序号为i的节点有:
(1)如果i>=0,则序号为i节点的双亲结点的序号为(i-1)/2;如果i=0,则序号i节点无双亲结点
(2)如果2i+1<n,则序号i结点的左孩子的序号为2i+1,右孩子的序号为2i+2;如果2i+1>=n,则序号i节点无孩子节点
原文链接:https://blog.csdn.net/zhuboke3344/article/details/78759501
两种代码实现方式
数组实现:
规定:
假设结点索引为index,那么它的左子结点的索引(下标)为:index2+1
右子结点为index2+2
方法:
1.树的创建和销毁
2.树中结点的搜索
3.添加与删除
4.遍历
class Tree
{
public:
Tree(int size,int *Root) //构造函数
{
my_Tree = new int[size];
length=size; //记录树的大小,多少个结点
for(int i=0;i<size;i++)
{
my_Tree[i]=0; //初始化
}
my_Tree[0]=*Root; //初始化一个根结点
}
~Tree()
{
delete[] my_Tree;
my_Tree=NULL;
}
int Search(int index) //搜索树
{
if(index<0||index>=length||my_Tree==0)
{
return NULL;
}
return my_Tree[index];
}
bool addTree(int index,int direction,int *Node) //给指定结点索引index添加子结点direction表示往左还是右插入结点Node ,
{
if(index<0||index>=length||my_Tree[index]==0)
{
return false;
}
if(direction==0) //往左边插入
{
if(my_Tree[index*2+1]!=0)
{
return false;
}
my_Tree[index*2+1]=*Node;
}
if(direction==1) //往右插入子结点
{
if(my_Tree[index*2+2]!=0)
{
return false;
}
my_Tree[index*2+2]=*Node;
}
}
bool popTree(int index,int *Node)
{
if(index<0||index>=length||my_Tree[index]==0)
{
return false;
}
*Node=my_Tree[index];
my_Tree[index]=0; //结点位置置为空
return true;
}
void Traverse()
{
for(int i=0;i<length;i++)
{
cout<<my_Tree[i]<<" ";
}
cout<<endl;
}
private:
int *my_Tree; //指针数组
int length; //结点长度
};
链表实现:
规定:
假设结点索引为index,那么它的左子结点的索引(下标)为:index2+1
右子结点为index2+2
方法:
创建树,销毁树,搜索结点,添加删除结点,前序遍历,中序遍历,后序遍历。
结点要素:索引(找到结点),数据(存储数据),左孩子指针(创建左子树),右孩子指针(创建右子树),父结点指针(删除结点的时候,要找到父结点,然后让父结点指向空)。
class Node //结点类
{
public:
int data; //数据
int index; //索引
Node *left; //左孩子指针
Node *right; //右孩子指针
Node *parent; //父结点指针
Node() //结点构造函数,初始化所有属性
{
index=0;
data=0;
left=NULL;
right=NULL;
parent=NULL;
}
void deleteNode() //先找到父节点,看是它的左孩子还是右孩子,然后再把父亲相应的指针指为空,然后再自杀 ,然后把它的子代结点全部销毁
{
if(this->left!=NULL)
{
this->left->deleteNode(); //用递归销毁左子树
}
if(this->right!=NULL)
{
this->right->deleteNode(); //用递归销毁右子树
}
if(this->parent!=NULL) //让父结点的指向变为空
{
if(this->parent->left==this)
{
this->parent->left=NULL;
}
if(this->parent->right==this)
{
this->parent->right=NULL;
}
}
delete this; //销毁自己
}
Node *SearchNode(int index) //查找搜索结点,使用递归
{
if(this->index==index)
{
return this;
}
Node *temp = NULL;
if(this->left!=NULL)
{
if(this->left->index==index)
{
return this->left;
}
else
{
temp=this->left->SearchNode(index);
if(temp!=NULL)
{
return temp;
}
}
}
if(this->right!=NULL)
{
if(this->right->index==index)
{
return this->right;
}
else
{
temp=this->right->SearchNode(index);
if(temp!=NULL)
{
return temp;
}
}
}
return NULL;
}
void preTraverse() //前序遍历:根结点->左结点->右结点
{
cout<<this->data<<" "<<this->index<<endl; //输出根结点的数据和索引
if(this->left!=NULL)
{
this->left->preTraverse(); //左子树结点
}
if(this->right!=NULL)
{
this->right->preTraverse(); //右子树结点
}
}
void inTraverse() //中序遍历:左子树->根结点->右子树,就是把根结点输出顺序改变了一下
{
if(this->left!=NULL)
{
this->left->inTraverse();
}
cout<<this->data<<" "<<this->index<<endl;
if(this->right!=NULL)
{
this->right->inTraverse();
}
}
void lastTraverse() //后序遍历:左子树->右子树->根结点
{
if(this->left!=NULL)
{
this->left->lastTraverse();
}
if(this->right!=NULL)
{
this->right->lastTraverse();
}
cout<<this->data<<" "<<this->index<<endl;
}
};
class Tree //二叉树类
{
public:
Tree() //构造函数
{
root = new Node();
}
Node *Search(int index) //搜索结点
{
return root->SearchNode(index);
}
bool addNode(int index,int direction,Node *node) //往指定的结点左右添加子结点
{
Node *temp = Search(index);
if(temp==NULL)
{
return false;
}
else
{
Node *pnode = new Node(); //把需要添加的结点赋给pnode
pnode->data=node->data;
pnode->index=node->index;
pnode->parent=temp; //找到父结点
if(direction==0)
{
temp->left=pnode;
}
if(direction==1)
{
temp->right=pnode;
}
}
return true;
}
bool deleteNode(int index,Node *node) //销毁结点以及其子代
{
Node *temp = Search(index);
if(temp==NULL)
{
return false;
}
if(node!=NULL)
node->data=temp->data;
temp->deleteNode();
return true;
}
~Tree() //析构函数
{
deleteNode(0,NULL); //从根结点开始删除
//root->deleteNode();
}
void preTraverse() //前序遍历
{
root->preTraverse();
}
void inTraverse() //中序遍历
{
root->inTraverse();
}
void lastTraverse() //后序遍历
{
root->lastTraverse();
}
private:
Node *root; //根结点
};
以上便是我对树的一点点浅薄的看法,后续还会更新哦。