二叉树是n个节点的有限集合,或者是空集,或者是由一个根节点以及两个互不相交的、分别称为左子树和右子树的二叉树组成(严格区分左子树和右子树,即使只有一个子节点)
二叉树性质:
二叉树第i个(i>=1)层上的结点最多为2i-1个。
深度为k(k>=1)的二叉树最多有2k-1个节点。满节点时称为满二叉树。
完全二叉树:只有最下面两层有度数小于2的节点,且最下面一层的叶节点集中在最左边的若干位置上。
具有n个节点的完全二叉树的深度为
log2(n+1)
顺序存储结构:完全二叉树节点的编号方法是从上到下,从左到右,根节点为1号节点。设完全二叉树的节点数为n,某节点编号为i,当i>1(不是根节点)时,有父节点,其编号为i/2;当2*i<=n时,有左孩子,其编号为2*I,否则没有左孩子,本身是叶节点. 当2*i+1<=n时,有右孩子,其编号为2*i+1,否则没有右孩子,
有n个节点的完全二叉树可以用有n+1个元素的数组进行顺序存储,节点号和数组下标一一对应,下标为零的元素不用。不完全二叉树可以采取增加虚拟节点的方式补充成完全二叉树,这样做会增加存储所需要的空间,浪费资源。
二叉树链式存储
先序遍历: 先根 再左 再右
中序遍历: 先左 再根 再右
后序遍历: 先左 再右 再根
tree.c
#include <stdio.h>
#include <stdlib.h>
#include "linkqueue.h"
bitree* tree_create()
{
data_t ch;
bitree* r;
scanf("%c",&ch);
if(ch=='#')
{
return NULL;
}
if((r=(bitree*)malloc(sizeof(bitree)))==NULL)
{
printf("malloc failed\n");
return NULL;
}
r->data=ch;
r->left=tree_create();
r->right=tree_create();
return r;
}
/*
先序遍历
*/
void preorder(bitree* r)
{
if(r==NULL)
{
return;
}
printf("%c",r->data);
preorder(r->left);
preorder(r->right);
}
/*
中序遍历
*/
void inorder(bitree* r)
{
if(r==NULL)
{
return;
}
inorder(r->left);
printf("%c",r->data);
inorder(r->right);
}
/*
后序遍历
*/
void postorder(bitree* r)
{
if(r==NULL)
{
return;
}
postorder(r->left);
postorder(r->right);
printf("%c",r->data);
}
void layerorder(bitree* r)
{
linkqueue *lq;
if((lq=queue_create())==NULL)
return;
if(r==NULL)
{
return;
}
else
{
printf("%c",r->data);
enqueue(lq,r);
while(!queue_empty(lq))
{
r=dequeue(lq);
if(r->left!=NULL)
{
printf("%c",r->left->data);
enqueue(lq,r->left)
}
if(r->right!=NULL)
{
printf("%c",r->right->data);
enqueue(lq,r->right)
}
}
}
}
linkqueue.c
#include <stdio.h>
#include <stdlib.h>
#include "linkqueue.h"
linkqueue *queue_create()
{
linkqueue *lq;
if((lq=(linkqueue *)malloc(sizeof(linkqueue)))==NULL)
{
printf("malloc failed");
return NULL;
}
lq->front=lq->rear=(linklist)malloc(sizeof(listnode));
if(lq->front==NULL)
{
printf("front malloc failed");
return NULL;
}
lq->front->data=0;
lq->front->next=NULL;
return lq;
}
int enqueue(linkqueue *lq,data_t x)
{
linklist p;
if(lq==NULL)
{
printf("lq is NULL");
return -1;
}
if((p=(linklist)malloc(sizeof(listnode))==NULL))
{
printf("node malloc failed");
return -1;
}
p->data=x;
p->next=NULL;
lq->rear->next=p;
lq->rear=p;
return 0;
}
/*
为了防止队列中只有一个元素节点时,删掉后rear只能指向NULL,
可以采取出队时删除掉头结点,然后把首元结点当作头结点的方法,
此时原本首元结点中的数据看作是无意义的
*/
data_t dequeue(linkqueue *lq)
{
linklist p;
if(lq==NULL)
{
printf("lq is NULL");
return NULL;
}
p=lq->front;
lq->front=p->next;
free(p);
p=NULL;
return (lq->front->data);
}
int queue_empty(linkqueue *lq)
{
if(lq==NULL)
{
printf("lq is NULL");
return -1;
}
return (lq->front==lq->rear?1:0);
}
int queue_clear(linkqueue *lq)
{
if(lq==NULL)
{
printf("lq is NULL");
return -1;
}
linklist p;
while(lq->front->next)
{
p=lq->front;
lq->front=p->next;
//printf("clear:%d\n",p->data);
free(p);
p=NULL;
}
return 0;
}
linkqueue *queue_free(linkqueue *lq)
{
if(lq==NULL)
{
printf("lq is NULL");
return NULL;
}
linklist p;
while(lq->front)
{
p=lq->front;
lq->front=p->next;
//printf("free:%d\n",p->data);现在data是指针了
free(p);
}
free(lq);
lq=NULL;
return NULL;
}
test.c
#include <stdio.h>
#include "linkqueue.h"
int main()
{
bitree *r;
if((r=tree_create())==NULL)
return -1;
preorder(r);
puts("");
inorder(r);
puts("");
postorder(r);
puts("");
layerorder(r);
puts("");
return 0;
}