数据结构之初探二叉树
树的一些基本概念:
树:N个节点组成的有限集合(N>=0)。
子树:上一个根节点的孩子,并且也是下一层子树的根节点。
二叉树:最多只有两个孩子节点的树。
空树:没有子节点的树。
非空树:
树中至少有一个节点——根。
树中各子树是互不相交的集合。
树的表示方法:
嵌套集合表示法,广义表法,凹入表示法。
树的基本术语:
结点:表示树中的元素,包括数据项及若干指向其子树的分支。
结点的度:结点拥有的子树个数。
叶子结点:度为0的结点。
树的度:一颗树中最大的结点度数(子树数)。
孩子:结点的子树的根称为该结点的孩子(结点)。
双亲:孩子结点的上一层结点叫该结点的父节点。
兄弟:同一双亲的孩子互称兄弟(结点)。
结点的层次 :从根节点算起根为第一层。
树的深度 :树中结点的最大层次数。
堂兄弟:其双亲在同一层的结点互称为堂兄弟
结点的祖先:从根节点到该结点所经分支上的所有结点。
结点的子孙:以某根节点为根的子树中的任一结点叫之。
有序树:树中各结点的子树从左到右有次序(不能互换)。
森林:
多棵互不相交的树构成的集合。
树
例如这就是一棵二叉树。
二叉树的基本特征:
1.每个结点最多只有两棵子树。
2.子树有左右之分,其次序不能任意颠倒,是一个有序树。
二叉树的几个基本性质:
一。
在二叉树的第i层上至多有2^(i-1)次方个结点。
二。
深度为k的二叉树上至多含2^k-1个结点。
三。
对任何一棵二叉树,若它含有N个叶子节点,N1个度为2的结点,则N=N1+1;
四。
具有N个结点的完全二叉树的深度为:
log2N(取整)+1.
五。
对于含有N个结点的完全二叉树从上到下且从左至右进行1至N的编号,则对完全二叉树中的任意一个编号为i的结点。
若i=1,该结点是二叉树的根,无双亲;否则编号为i/2向上取整的结点为其双亲。
若2i>n, 则该结点无左孩子,否则编号为2i的结点无右孩子结点,否则,编号为2i+1的结点为其右孩子结点,
若2i+1>n,则该结点无右孩子结点,否则编号为2i+1的结点为其右孩子结点。
满二叉树:
指的是深度为K且含有2^(k)-1个结点的二叉树。
特点:每一层的结点树都是最大结点数
性质:第i层上至多有2^(i-1)个结点。
性质:深度为K的二叉树至多有2^k-1个结点。
完全二叉树:
若一棵二叉树中所含的N个结点与满二叉树中编号为1至N的结点一一对应(编号和位置一一对应)。
特点:
1.叶子节点只可能在层次最大的两层上出现。
2.对任一结点,若其右分支下子孙的最大层次为1.则其左分支下子孙的最大层次必为1或1+1.
下面将附上用二叉链表的方式建立二叉树,并且用#占位,显示先中后三种遍历方式:
/*************************************************************************
> File Name: mytree.c
> Author: zmr
> Mail: 1797763610@qq.com
> Created Time: Sun 03 May 2015 02:46:57 PM CST
************************************************************************/
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<stdlib.h>
#define PE '#'
typedef struct tree{ //定义树结点结构
char ele;
char nous[3]; //由与内存对齐问题先用数组占位
#ifndef SYSTEM32
char nouse[4];
#endif
struct tree *lchd,*rchd;
}_tree;
typedef struct quenode{ //队列结点
_tree *root;
struct quenode *next;
}_que;
typedef struct nodectl{ //队列控制结构
_que *head,*tail;
int lenth;
}_quectl;
typedef struct treectl { //树的控制结构
_tree *root;
int nodes;
#ifndef SYSTEM32
char nous[4];
#endif
}_treectl;
enum { CMD=0,STR };
void inq(_quectl *qctl,_tree *tree) //队列的入队操作
{
_que * qnode = NULL;
if(NULL == qctl || NULL == tree){
return ;
}
qnode = (_que*)malloc(sizeof(_que));
if(NULL == qnode){
return ;
}
qnode->root = tree;
qnode->next = NULL;
if(0 == qctl->lenth){
qctl->head=qctl->tail=qnode;
}else{
qctl->tail->next = qnode;
qctl->tail = qnode;
}
qctl->lenth += 1;
}
_tree *deq (_quectl *qctl) //删除一个队列结点
{
_que * qnode = NULL ;
_tree * tree = NULL ;
if(NULL == qctl || 0 >= qctl->lenth){
return NULL;
}
qnode = qctl->head;
qctl->head = qnode->next;
qctl->lenth -= 1;
tree = qnode->root;
free(qnode);
return tree;
}
void que_destory(_quectl *qctl) //破坏队列
{
_que * qnode = NULL;
if(NULL == qctl){
return ;
}
qnode = qctl->head;
while(NULL != qnode){
qctl->tail = qnode->next;
if(PE == qnode->root->ele){
free(qnode->root);
}
free(qnode);
qnode = qctl->tail;
}
}
void tree_create(_treectl *ctl,char *str) //建立二叉树
{
_tree *root = NULL,*mtree = NULL;
_tree *left = NULL,*right = NULL;
int index=0 ,lenstr = 0 ;
_quectl qctl = {NULL,NULL,0} ;
if(NULL == ctl || NULL == str){
return ;
}
ctl->root = NULL ;
ctl->nodes = 0 ;
lenstr = strlen(str);
if(0 >= lenstr){
return ;
}
mtree =(_tree *)malloc(sizeof(_tree));
if(NULL == mtree){
return ;
}
mtree->ele = str[0];
mtree->lchd= mtree->rchd =NULL;
ctl->root = mtree;
inq(&qctl,mtree);
index += 1;
while(index < lenstr){
mtree = deq(&qctl);
if(NULL == mtree){
break ;
}
left = (_tree *)malloc(sizeof(_tree));
right= (_tree *)malloc(sizeof(_tree));
memset(left,0x00,sizeof(_tree));
memset(right,0x00,sizeof(_tree));
left->ele = str[index];
right->ele= str[index+1];
inq(&qctl,left);
inq(&qctl,right);
if(PE == mtree->ele){ //遇到#给它的左右子树分别赋值NULL
left->ele = PE;
right->ele= PE;
free(mtree);
}else{
if(PE == left->ele){
mtree->lchd = NULL;
}else{
mtree->lchd = left;
}
if(PE == right->ele){
mtree->rchd = NULL;
}else{
mtree->rchd = right;
}
}
index += 2;
}
que_destory(&qctl);
}
void tree_destory(_tree *tree) //删除一棵树
{
if(tree){
tree_destory(tree->lchd);
tree_destory(tree->rchd);
free(tree);
}
}
void pre(_tree *tree) //前序遍历一棵树
{
if(tree)
{
printf("%c ",tree->ele);
pre(tree->lchd);
pre(tree->rchd);
}
}
void middle(_tree *tree) //中序遍历一颗树
{
if(tree){
middle(tree->lchd);
printf("%c ",tree->ele);
middle(tree->rchd);
}
}
void post(_tree *tree) //后序遍历一颗树
{
if(tree)
{
post(tree->lchd);
post(tree->rchd);
printf("%c ",tree->ele);
}
}
int dowork(int ac,char **av)
{
_treectl mytree = {NULL,0};
int height = 0;
_tree *node = NULL;
if(ac <= STR){
printf("NO input\n");
return -1;
}
tree_create(&mytree,av[STR]);
pre(mytree.root);
printf("\n");
middle(mytree.root);
printf("\n");
post(mytree.root);
printf("\n");
tree_destory(mytree.root);
return 0;
}
int main(int ac,char **av)
{
return dowork(ac,av);
}