今日学习了二叉树有关知识。
二叉树
二叉树通俗来讲就是一个有俩个指针的链表。他们大多长这个样子:
这里还有俩个概念了,二叉树分为完全二叉树和满二叉树
上面所说的是满二叉树,顾名思义就是每个父节点都相应的有俩个指针,通常左边的叫左孩子或者左子树,右边的叫右孩子或者右子树。
而完全二叉树是可以在最底端的右边连续的没有节点比如下面这俩个:
这俩个都是完全二叉树。
这里扩展一下堆:堆是一个完全二叉树。堆(Heap)是计算机科学中一类特殊的数据结构,是最高效的优先级队列。堆通常是一个可以被看做一棵完全二叉树的数组对象。堆中的某个节点的值总是不大于或者不小于其父节点。根节点最大的堆叫做最大堆或者大根堆,根节点最小的堆叫做最小堆或者小根堆。常见的堆有二叉堆和斐波拉契堆。堆是非线性结构。
二叉树有四种遍历方式:
先序遍历,中序遍历,后序遍历,层序遍历。
前面三种是根据根节点的次序划分的,先序遍历就是先遍历根节点,再依次是左子树,右子树。中序遍历就是把根节点放在中间,是左根右的结构(左子树,根节点,右子树)。后序遍历是把根节点放在最后的,所以它的遍历是左右根。而层序遍历就是一层一层遍历。
如果按照上面所说的遍历方式,那么:
先序遍历:1->2->4->8->9->5->3->6->7
中序遍历:8->4->9->2->5->1->6->3->7
后序遍历:8->9->4->5->2->6->7->3->1
层序遍历:1->2->3->4->5->6->7->8->9
如果还是不太能够理解这些遍历的方式,我强烈推荐大家去看这篇文章二叉树三种遍历(动态图+代码深入理解)_杨 戬的博客-CSDN博客_写出如下二叉树三种遍历的结果写的很好,很浅显易懂。
然后就是代码实现咯。
1.我们创建有左右俩个指针的结构体。
2.在创建的时候我用的是先序顺序去创建,因为这样子好写一点。然后我写的是递归写法,判断当前的数字是不是0,是0就返回NULL,如果不是那么可以继续左右创建。(当然输入的时候如果末尾的节点没有左节点或者右节点,我们是需要输入俩个0的)。
3.输出遍历方式,运用递归也是蛮简单的,按照先序遍历的话,就是先输出根节点,再把左子树拿去遍历即可。而中序就是利用递归的思想,先调用head->lnext;然后输出根节点,最后调用head->rnext;而后序也是一样的道理。
#include<stdio.h>
#include<malloc.h>
typedef struct node
{
int x;
struct node *lnext;
struct node *rnext;
}NODE;
NODE* creat()
{
int k;
NODE *head;
scanf("%d",&k);
if(k==0) return NULL;
head=(NODE *)malloc(sizeof(NODE));
head->x=k;
head->lnext=creat();
head->rnext=creat();
return head;
}
int xxput(NODE *head)
{
if(head==NULL) return 0;
printf("%d ",head->x);
xxput(head->lnext);
xxput(head->rnext);
}
int zxput(NODE *head)
{
if(head==NULL) return 0;
zxput(head->lnext);
printf("%d ",head->x);
zxput(head->rnext);
}
int hxput(NODE *head)
{
if(head==NULL) return 0;
hxput(head->lnext);
hxput(head->rnext);
printf("%d ",head->x);
}
int main()
{
NODE *head;
puts("请输入你所要创建的二叉树先序遍历(输入0代表结束当前子树):");
head=creat();
puts("先序遍历为:");
xxput(head);
puts("");
puts("中序遍历为:");
zxput(head);
puts("");
puts("后序遍历为:");
hxput(head);
puts("");
return 0;
}