文章目录
二叉树的创建
普通二叉树的创建,这里以完全二叉树的创建为例,所谓完全二叉树,也就是从根节点开始,一层一层的往后接入节点,首先我们创建一个结构体,用来存储二叉树的节点,每一个节点除了存一个data,还有一个左孩子和一个右孩子。
#include<stdio.h>
#include<algorithm>
using namespace std;
struct BiTree{
int data;
BiTree *left;
BiTree *right;
};
void createBiTree(BiTree* &T) {
int data;
scanf("%d", &data);
if(data == -1)
return;
T = new BiTree();
T->data = data;
createBiTree(T->left);
createBiTree(T->right);
}
int main() {
BiTree *T;
createBiTree(T);
return 0;
}
如果我们想要创建一个下图所示的树,需要输入
3 6 -1 -1 7 -1 -1
因为首先3是根节点,然后是3这个节点的左孩子左孩子,输入了6,然后是6这个节点的左孩子,没有输入-1,然后是6这个节点的右孩子,也没有,输入-1,然后是3这个节点的右孩子,输入7,然后是7这个节点的左孩子,没有是-1,右孩子也没有,也是-1。
二叉排序树的创建
二叉排序树的创建核心是进行节点的插入,每个需要插入的节点都是从根节点开始比较,把小的节点放到左边,大的节点放到右边,其中中序遍历即是从小到大输出该树的所有节点,对于一颗完全二叉排序树,其查找速度是O(logn),但是不得不说一下极限,也就是当我们创建二叉排序树的时候,所有的孩子都在一侧,那么该树就成了线性结构,其查找的时间复杂度是O(n),为了解决这一问题,有一个叫做平衡二叉树的东西,比较有名气的一个算法是红黑树实现二叉树的自平衡,红黑树在JDK1.8,HashMap中就有用到,详细介绍可以看下HashMap底层。
#include<stdio.h>
#include<algorithm>
using namespace std;
struct BiSortTree{
int data;
BiSortTree *left;
BiSortTree *right;
};
void insertChild(BiSortTree* T,int data) {
if (data < T->data) {
if(T->left == NULL) {
T->left = new BiSortTree();
T->left->data = data;
//printf("left***if\n");
} else {
//printf("left***else");
insertChild(T->left,data);
}
}
else {
if(T->right == NULL) {
T->right = new BiSortTree();
T->right->data = data;
//printf("right***if\n");
} else {
//printf("right***else\n");
insertChild(T->right,data);
}
}
}
void createBiSortTree(BiSortTree* T) {
int data;
scanf("%d",&data);
T->data = data;
while(1) {
scanf("%d", &data);
if (data == -1)
break;
insertChild(T,data);
}
}
int main() {
BiSortTree *T = new BiSortTree();
createBiSortTree(T);
return 0;
}
如果我们输入如下图的6个数字,那么,他会自动构造出如下图的一颗二叉排序树。
树的先序、中序、后续遍历
先序遍历是“根左右”,中序遍历是“左根右”,后序遍历是“左右根”。
二叉树的这三种遍历通过递归实现,对于先序遍历,以一个只有三个节点的满二叉树来说,第一次输出了根节点,然后遍历其左孩子,并把左孩子输出,然后遍历根节点的右孩子,并把右孩子输出。中序遍历和后序遍历跟先序遍历都差不多的思想,值得一提的是,对于二叉排序树,其中序遍历就是其从小到大(或从大到小)输出,因为中序遍历是左根右,而二叉排序树刚好就是左孩子都比根小,而根都比右孩子小。
void pre(BiTree* T)
{
if(T!=NULL)
{
printf("%d ",T->data);
pre(T->left);
pre(T->right);
}
}
void mid(BiTree* T)
{
if(T!=NULL)
{
mid(T->left);
printf("%d ",T->data);
mid(T->right);
}
}
void post(BiTree* T)
{
if(T!=NULL)
{
post(T->left);
post(T->right);
printf("%d ",T->data);
}
}
树的层次遍历
层次遍历是通过队列这个数据结构实现的,队列是先进先出,这里还是以一个只有三个节点的满二叉树进行描述,第一次是把根节点入队列,然后把根节点弹出,并输出根节点,然后判断该节点的左孩子是否为空,如果非空,那就入队列,然后判断右孩子是否为空,非空就入队列,这样也就是从左到右依次入队列的,所以,输出的时候,也是从左到右依次输出,即达到层次遍历的目的
void level(BiTree* T) {
queue<BiTree*> que;
if (T != NULL) {
que.push(T);
}
BiTree* p;
while(!que.empty()) {
p = que.front();
que.pop();
printf("%d ",p->data);
if(p->left != NULL)
que.push(p->left);
if(p->right != NULL)
que.push(p->right);
}
}