以下内容源于慕课网的学习整理,如有侵权,请告知删除。
树存在概念中,是对数组或者链表的一种操作方式的概念。
一、与树有关的一些基础概念
(1)树
- 有限节点的集合;
(2)度
- 某个节点的直接孩子数目;
(3)叶节点
- 终端节点
(4)祖先
- 所有在它之上的节点
(5)深度
- 节点的深度(节点所处的位置)
- 树的深度(整棵树的深度)
(6)二叉树
- 所有节点的度都小于等于2
(7)二叉树的遍历
- 前中后,是针对“根”来说的。
(8)作用实例
- 人机对战
二、二叉树的数组实现
1、换算公式
- 父节点下标*2+1,得到,父节点的左孩子节点的下标;
- 父节点下标*2+2,得到,父节点的右孩子节点的下标
2、示意图
- 括号里面表示的是索引,或者说节点序号,外面的是数据。
- 慕课网中只是按照这个图,来进行查找(遍历查找)、插入(已经确定在哪个位置上出入了)、删除(删除后赋值为0)等操作。
三、二叉树的链表实现
1、节点要素
- 数据,左孩子指针,右孩子指针,父指针,索引(这里用来表征节点的序号)
2、删除元素
- 要求把对应的子节点也删除掉;
- 也可能要求只删除该点,然后该点的孩子节点指向该点的父节点;
3、前序遍历(根左右)
4、中序遍历(左根右)
首先是左526,然后是根0,接着是右897;
然后对526进行同样的操作,即左是2,根是5,右是6,则排序结果是256;
同理对897进行同样的操作,即左是9,根是8,右是7,则排序结果是987;
最后合成为256 0 987。
5、后序遍历(左右根)
首先是左526,然后是右897,接着是根0;
然后对526进行同样的操作,即左是2,右是6,根是5,则排序结果是265;
同理对897进行同样的操作,即左是9,右是7,根是8,则排序结果是978;
最后合成为265 978 0。
6、编码实现
- 树类、节点类;
- 节点类包含五要素:数据,左孩子指针,右孩子指针,父指针,索引(这里用来表征节点的序号)
- 前序遍历(中序遍历、后序遍历就调换相应的位置即可)。
- 对树的遍历操作,落实在根节点调用遍历函数。
node.h
#ifndef NODE_H
#define NODE_H
class Node{
public :
Node();
int index;
int data;
Node *pLNOde;
Node *pRNode;
Node *pParent;
Node *SerchNode(int index);
void deleteNode();
void Preorder();
void Midorder();
void Postorder();
};
#endif
node.cpp
#include "Node.h"
#include <iostream>
using namespace std;
Node::Node()
{
index=0;
data=0;
pLNOde=NULL;
pRNode=NULL;
pParent=NULL;
};
Node* Node::SerchNode(int index)
{
Node *temp=NULL;
if (this->index==index)
return this;
if (this->pLNOde!=NULL)
{
temp=this->pLNOde->SerchNode(index);
if (temp!=NULL)
{
return temp;
}
}
if (this->pRNode!=NULL)
{
temp=this->pRNode->SerchNode(index);
if (temp!=NULL)
{
return temp;
}
}
return NULL;
};
void Node::deleteNode()
{
if(this->pLNOde!=NULL)
{
this->pLNOde->deleteNode();
}
if (this->pRNode!=NULL)
{
this->pRNode->deleteNode();
}
if (this->pParent!=NULL)
{
if (this->pParent->pLNOde==this)
{
this->pParent->pLNOde=NULL;
}
if (this->pParent->pRNode==this)
{
this->pParent->pRNode=NULL;
}
}
delete this;
};
void Node::Preorder()
{
cout<<this->data<<" "<<this->index<<endl;
if (this->pLNOde!=NULL)
{
this->pLNOde->Preorder();
}
if (this->pRNode!=NULL)
{
this->pRNode->Preorder();
}
};
void Node::Midorder()
{
if (this->pLNOde!=NULL)
{
this->pLNOde->Midorder();
}
cout<<this->data<<" "<<this->index<<endl;
if (this->pRNode!=NULL)
{
this->pRNode->Midorder();
}
};
void Node::Postorder()
{
if (this->pLNOde!=NULL)
{
this->pLNOde->Postorder();
}
if (this->pRNode!=NULL)
{
this->pRNode->Postorder();
}
cout<<this->data<<" "<<this->index<<endl;
};
#ifndef Tree_H
#define Tree_H
#include "Node.h"
class Tree
{
public:
Tree();
~Tree();
Node *SerchNode(int index);//查找索引为index的那个节点,并返回指向该节点的指针
bool addNode(int index,int direction,Node *node);//添加,在索引为index的节点上,添加一个节点node
//左右方向由direction决定
bool deleteNode(int index,Node *node);//删除
void Preorder();//前序
void Midorder();//中序
void Postorder();//后序
private:
Node *p_node;
};
#endif
tree.cpp
#include "Tree.h"
#include "Node.h"
#include <iostream>
using namespace std;
Tree::Tree()
{
p_node=new Node();
};
Tree::~Tree()
{
deleteNode(0,NULL);//这里调用的是tree中的删除节点函数,从根节点(0)开始
};
Node *Tree::SerchNode(int index)
{
return p_node->SerchNode(index);
};
bool Tree::deleteNode(int index,Node *node)
{
Node *temp=SerchNode(index);
if (temp!=NULL)
{
if (node!=NULL)//传入的Node可以为null。是null时,表明不需要把要删除的节点的数据保存。
{
node->index=temp->index;
node->data=temp->data;
}
temp->deleteNode();
return true;
}
else
return false;
};
bool Tree::addNode(int index,int direction,Node *node)
{
Node *temp=SerchNode(index);
if (temp)
{
Node *NewNode=new Node();
if (NewNode==NULL)
{
return false;
}
NewNode->data=node->data;
NewNode->index=node->index;
if (direction==0)
{
temp->pLNOde=NewNode;
NewNode->pParent=temp;
}
if (direction==1)
{
NewNode->pParent=temp;
temp->pRNode=NewNode;
}
return true;
}
return false;
};
void Tree::Preorder()
{
p_node->Preorder();
}
void Tree::Midorder()
{
p_node->Midorder();
}
void Tree::Postorder()
{
p_node->Postorder();
}
test.cpp
#include "Node.h"
#include "Tree.h"
#include <iostream>
using namespace std;
/*
0(0)
1(1) 2(2)
5(3) 7(4) 6(5) 9(6)
*/
int main()
{
Tree *p=new Tree;//这里的p是指向根节点的指针
Node *n2=new Node;
n2->data=1;
n2->index=1;
Node *n3=new Node;
n3->data=2;
n3->index=2;
Node *n4=new Node;
n4->data=3;
n4->index=3;
Node *n5=new Node;
n5->data=4;
n5->index=4;
Node *n6=new Node;
n6->data=5;
n6->index=5;
Node *n7=new Node;
n7->data=6;
n7->index=6;
Node *n8=new Node;
n8->data=8;
n8->index=8;
Node *n9=new Node;
n9->data=9;
n9->index=9;
Node *n10=new Node;
n10->data=10;
n10->index=10;
Node *n11=new Node;
n11->data=11;
n11->index=11;
p->addNode(0,0,n2);
p->addNode(0,1,n3);
p->addNode(1,0,n4);
p->addNode(1,1,n5);
p->addNode(2,0,n6);
p->addNode(2,1,n7);
// p->addNode(4,0,n8);
// p->addNode(4,1,n9);
// p->addNode(6,0,n10);
// p->addNode(6,1,n11);
Node *n18=new Node;
n18=p->SerchNode(10);
if (n18!=NULL)
{
cout<<"index:"<<n18->index<<endl;
}
//Node *n12=new Node;
//p->deleteNode(6,n12);
p->Preorder();
cout<<"========================="<<endl;
p->Postorder();
cout<<"========================="<<endl;
p->Midorder();
delete p;
p=NULL;
system("pause");
return 0;
}