#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#define MaxSize 100
typedef struct {
int id;
}ElemType;
/*以下为顺序存储二叉树,由于只有当树为完全二叉树的时候,树的结点和数组下标有关系
* 但当不是完全二叉树的时候,就要花费大量的空间去存储空值,造成了大量的内存浪费
* 因此一般不用顺序存储*/
struct Tree{
ElemType value;
bool isEmpty;
};
struct Tree t[MaxSize];//表示一棵二叉树
void InitTree(){
for (int i = 0; i < MaxSize; ++i) {
t[i].isEmpty=true;
}
}
/*
*
*
* */
/*链式存储
* */
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild,*rchild;
//struct BiTNode *parent;//如果经常找父节点,可以使用这种三叉链表
}BiTNode,*BiTree;
/*基于队列的遍历*/
typedef struct st{
BiTNode *data;
struct st *next;
}LinkNode;
typedef struct {
LinkNode *front,*rear;//带头结点中,front指向头结点,rear指向尾结点
}LinkQueue;
void visit(BiTNode *T);
BiTNode *treeInsertLeft(BiTNode *R,ElemType a);
BiTNode *treeInsertRight(BiTNode *R,ElemType a);
void PreOrder(BiTree T);
void InOrder(BiTree T);
void BackOrder(BiTree T);
int treeDepth(BiTree T);
void levelOrder(BiTree T);
int main() {
//creat a tree
BiTree root = (BiTree) malloc(sizeof(BiTNode));
//initialized a tree
root->lchild=NULL;
root->data.id = 1;
root->rchild=NULL;
//insert a node
ElemType a={1},b={2},c={3},d={4},e={5},f={6},g={7},h={8};
BiTNode *an,*bn,*cn,*dn,*en,*fn,*gn,*hn;
bn=treeInsertLeft(root,b);
cn=treeInsertRight(root,c);
dn=treeInsertLeft(bn,d);
en=treeInsertRight(bn,e);
fn=treeInsertLeft(cn,f);
gn=treeInsertRight(cn,g);
PreOrder(root);
printf("\n");
InOrder(root);
printf("\n");
BackOrder(root);
printf("\n");
treeDepth(root);
levelOrder(root);
return 0;
}
/*这里只需要一层指针就ok了,根本不需要指针的指针,注意理解指针的本质
* 我们创建的都是链表结点的指针,因此修改结点只需要把结点的指针在函数之间进行传递就行了,不需要修改指针,只需要修改结点*/
BiTNode *treeInsertLeft(BiTNode *R,ElemType a){
BiTNode *p = (BiTNode *) malloc(sizeof(BiTNode));
p->rchild=NULL;
p->lchild=NULL;
p->data=a;
R->lchild=p;
return p;
}
BiTNode *treeInsertRight(BiTNode *R,ElemType a){
BiTNode *p = (BiTNode *) malloc(sizeof(BiTNode));
p->rchild=NULL;
p->lchild=NULL;
p->data=a;
R->rchild=p;
return p;
}
/*递归遍历
*
*
* */
//先续遍历
void PreOrder(BiTree T){
if (T!=NULL){
visit(T);
PreOrder(T->lchild);
PreOrder(T->rchild);
}
}
//中序遍历
void InOrder(BiTree T){
if (T!=NULL){
InOrder(T->lchild);
visit(T);
InOrder(T->rchild);
}
}
//后序遍历9 void BackOrder(BiTree T){
if (T!=NULL){
BackOrder(T->lchild);
BackOrder(T->rchild);
visit(T);
}
}
/*先中后续遍历可以转换求前中后缀表达式*/
void visit(BiTNode *T) {
printf("%d",T->data.id);
}
/*求树的深度*/
/*递归从逻辑的本质上就是树的遍历,比如求阶乘,就是度为1的树的遍历
* 求斐波那契数列,就是度为2的树的前续遍历
* 通过递归的方式把一个问题分解为规模最小的情况,但是数量最多。这点十分像树,从一个根开始生长,生长到最后的全是叶子,再从叶子一步步返回都根
* 在生长的过程中,通过类似n-1的操作是的问题规模变小,通过出口条件判断来限定最小规模条件,通过return语句来执行返回到根的操作(由零到整)
* 总之是,化整为零,由零到整
* 一颗树从生长到无数叶子,每个叶子代表着一种递归的可能性*/
int treeDepth(BiTree T){
if(T==NULL){
return 0;
} else{
int l=treeDepth(T->lchild);
int r=treeDepth(T->rchild);
return l>r? l+1:r+1;
}
}
/*层次遍历
*
* 设置一个辅助队列*/
bool Empty(LinkQueue *Q){
if (Q->front->next==NULL)
return true;
else
return false;
}
/*尾插法*/
void EnQueue(LinkQueue *Q,BiTNode *z){
LinkNode *s = (LinkNode *) malloc(sizeof(LinkNode));
s->data=z;
s->next=NULL;
Q->rear->next=s;
Q->rear=s;
}
bool DeQueue(LinkQueue *Q,BiTNode **s){
if (Empty(Q)){
return false;
}
LinkNode *p=Q->front->next;
*s=p->data;
Q->front->next=Q->front->next->next;
if(Q->rear==p)
Q->rear=Q->front;
free(p);
return true;
}
void levelOrder(BiTree T){
LinkQueue *Q=(LinkQueue *)malloc(sizeof(LinkQueue));
(*Q).rear = (*Q).front = (LinkNode *) malloc(sizeof(LinkNode));
BiTree p;
EnQueue(Q,T);
while (!Empty(Q)){
DeQueue(Q,&p);
visit(p);
if (p->lchild!=NULL){
EnQueue(Q,p->lchild);
}
if (p->rchild!=NULL){
EnQueue(Q,p->rchild);
}
}
}