基于链式存储的二叉树的操作
1:遍历:先序(根-左-右) 中序(左-根-右),后序(左-右-根)
先序遍历:第一个访问的结点:根结点;最后一个访问的结点:最右下角那个结点
中序和后序开头第一个访问的结点:最左下角那个结点
后序:最后一个:根结点
2:后序遍历序列和层次遍历序列相同的非空二叉树是:只有根节点的树
3:一棵有124个叶子结点的完全二叉树最多有(248)个结点
解:某一层次的叶子总数公式:n=2^(k-1) 得出k=8层;
从1层到i层的结点总数公式:n=2^i-1; 故而1-7层总数=(128)-1=127
而第7层的结点数2^6=64; 设最后一层(第8层)的结点数为n8;n8为偶数 124=n8+64-n/2 得n8=120; n8为奇数:124=n8+64-(n+1)/2 得n8=121
故而总结点数=121+127=248
4:具有1000个结点的完全二叉树次底层的叶子结点数:(11)
解:2^10-1=1023 ,1-9层的结点总数:2的9次方-1=511;故而有10层 1000-511=489,第10层总数=489,第9层有孩子的结点数:(489+1)/2=245,第9层总结点数2的8次方=256 故而9层的叶子结点=256-245=11
5:先序和后序正好相反的非空二叉树是:(左单支和右单支树)
6:先序和中序相同的树的特征是:各结点均无左孩子
7:任何一棵二叉树至少有一个度为2的结点(X)
typedef int TElemtype;
typedef char Elemtype;
#define Increament 100
#define Status int
#define Error -1
#define ok 0
#define True 1
#define BiInit_Size 100
#define MaxSize 100//队列用
//#define Link 0
//#define Thread 1
typedef struct BiTNode{//二叉树的二叉链表
TElemtype data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
typedef BiTree BElemtype;
//-------树所用队列-----------//
typedef struct QDataNode{
BiTNode data;
}QDataNode,*BiQDataLink;
typedef struct BiHNode{
QDataNode *front;
QDataNode *rear;
}BiHNode,*BiQLink;
//-------树所用队列-----------//
//----------------------先序遍历式递归创建二叉树---------------------//
void CCreateBiTree(BiTree *T){
TElmetype ch;
printf("输入树之元素");
scanf("%d",&ch);
if(ch==0) *T=NULL;
else{
*T=(BiTNode *)malloc(sizeof(BiTNode));
(*T)->data=ch;
CCreateBiTree(&(*T)->lchild);
CCreateBiTree(&(*T)->lchild));
}
}
输入 1 2 3 0 0 4 5 0 6 0 0 7 0 0 0
//-----------------------------先序遍历--------------//
Status PreVisitBiTree(BiTNode *T){
if(T!=NULL){
printf("%d ",T->data);//根
PreVisitBiTree(T->lchild);//左
PreVisitBiTree(T->rchild);//右
}
}
//--------------------------------“后序”求树深--------//
int depthval=0,depthleft=0,depthright=0;
Status LastTraverseBiDepth(BiTNode *T){
if(!T) return 0;//空树
if (!T->lchild && !T->rchild) return 1;//树根
depthleft=LastTraverseBiDepth(T->lchild);//左
depthright=LastTraverseBiDepth(T->rchild);//右
depthval=1+(depthleft>=depthrihgt?depthleft:depthright);//总
return depthval;
}
//---------------------------------叶子结点数-------//
//思想:其左子树与右子树皆空 则为叶子结点
int count=0;
Status Allleftcount(BiTree T){
if(T){
if((!T->lchild) && (!T->rchild)) count++;
Allleafcount(T->lchild);
Allleafcount(T->rchild);
}
}
//----------------------------层次遍历---------------------//
Status Init_BiQueue(BiQLink *Q){
(*Q)=(BiQLink)malloc(sizeof(BiHNode));
(*Q)->rear=(*Q)->front=(BiQDataLink)malloc(sizeof(QDataNode)*(MaxSize));
if(!(*Q)->front) return Error;
return ok;
}
Status EnBiQueue(BiQLink *Q,BiTree T){
if((*Q)->rear-(*Q)->front==MaxSize-1) return Error;//因为第一个结点不用
(*Q)->rear++;
(*Q)->rear->data=*T;
return ok;
}
Status DeBiQueue(BiQLink *Q,BiTree *T){
if((*Q)->front==(*Q)->rear) return Error;//大哥 不能再退了
(*Q)->front++;
*(*T)=(*Q)->front->data;
return ok;
}
Status IsBiQueueEmpty(BiQLink *Q){
if((*Q)->rear==(*Q)->front) return True;
else return 0;
}
//-层次遍历要利用先进先出的特性,故而选queue做辅助-----//
Status floorTraverse(BiTree T){//层次遍历
BiQLink *Q;
Q=(BiQLink)malloc(sizeof(BiHNode));
Init_BiQueue(Q);
EnBiQueue(Q,T);//先要进一个
while(!IsBiQueueEmpty(Q)){
DeBiQueue(Q,&T);//一直出队就好了
printf("<->%2d",T->data);
if(T->lchild!=NULL) EnBiQueue(Q,T->lchild);//其有左孩,左孩进队
if(T->rchild!=NULL) EnBiQueue(Q,T->rchild);//
}
}//先进-循环内出队打印
//-------------------总测试----------------------//
void BiTreetest(){
BiTNode *T;//在其处创建的是指针 故而下面的就不需要取值符号 若是BiTNode T后面就需要指针
// T=(BiTNode *)malloc(sizeof(BiTNode));
CCreateBiTree(&T);
PreVisitBiTree(T);//此时的T已经是地址(指针)
LastTraverseBiDepth(T);
Allleafcount(T);
// f63(T,)
printf("\二叉树树深度%d",depthval);
printf("\n叶子节点个数:%d",count);
printf("\n层次遍历结果为:");
floorTraverse(T);
return 0;
}
中序遍历非递归算法
要用到栈
typedef struct BiStack{
BElemtype *top;//树指针型的指针
BElemtype *base;
TElemtype stacksize;//上面宏定义有
}BiStack;
Status InitBiStack(BiStack *s){//栈指针
s->base=(BiStack *)malloc(BiInit_Size*sizeof(BiStack));
if(!s->base) return Error;
s->top=s->base;
s->stacksize=BiInit_Size;
return ok;
}
Status BiPush(BiStack *s,BElemtype e){//进来个树形指针
if(s->top-s->base=s->stacksize){
s->base=(BElemtype *)realloc(s->base,sizeof(BElemtype)*(BiInit_Size+Increament));
s->top=s->base+s->stacksize;
s->stacksize+=Increament;
}
*(s-top)=e;
s->top++;
return ok;
}
Status IsBiStackEmpty(BiStack *s){
if(s->base==s->top) return 1;//确实是空
else return 0;//不空
}
Status BiPop(BiStack *s,BElemtype *p){//退栈 指向树形指针的指针
if(s->base==s->top) return Error;
s->top--;
*p=*(s->top);//*(指向树形指针的指针)=树形指针
return ok;
}
BiTree GoFarLeft(BiTree T,BiStack *s){//走到最后一个**左结点**的函数
if(!T) return NULL;
while(T->lchild){
BiPush(s,T);//若其有左子树 则当前结点T入栈
T=T->lchild;
}
return T;//此时的T为最左下脚那个没有左子树的结点
}
Status InOrderBiTraverse(BiTree T){
BiStack s;InitBiStack(&s);
BiTree t=NULL;
t=(BiTNode *)malloc(sizeof(BiTNode));
t=GoFarLeft(T,&s);
while(t){
printf("正在遍历的元素%d",t->data);//中序遍历的打印函数在while里面
if(t->rchild) t=GoFarLeft(t->rchild,&s);//如果该结点有右子树,则从该结点的右子树出发,走到该右子树的最左下角结点
else if(!IsBiStackEmpty(&s)) BiPop(&s,&t);// 如果木有右子树且不空 则出栈
else {break;}
}
}
BiTree PreGoFarLeft(BiTree T,BiStack *s){//先序遍历的打印函数在 此函数里面
printf("%d",T->data);
while(T->lchild){
BiPush(s,T);
T=T->lchild;
printf("%d",T->data);
}//走到最左下角结点
return T;
}
//-----------------------------------先序遍历非递归---------------------//
Status PreOrderTraverse(){//思想:每次都:“一有机会就向左疯狂输出”
BiStack s;InitBiStack(&s);
BiTree t=NULL;
t=(BiTree)malloc(sizeof(BiTNode));
t=GoFarLeft(T,&s);//先序和中序都要先跑到最左下角
while(t){
if(t->rchild) t=PreGoFarLeft(t->rchild,&s);
else if(!IsBiStackEmpty(&s)) BiPop(&s,&t);
else break;
}
}
void MyInorderTraverseTest(){
BiTree T;//在其处创建的是指针 故而下面的就不需要取值符号 若是BiTNode T后面就需要指针
CCreateBiTree(&T);
printf("-----------二叉树中序遍历非递归算法--------\n");
InorderBiTraverse(T);
printf("\n----------先序遍历-----------------------\n");
PreOrderTraverse(T);
return ok;
}
结果如下: