一、题目描述:
二叉树采用左右链存储,完成以下算法,要求算法尽可能的高效:
1)判断二叉树是否为完全二叉树。
2)输入二叉树的倒数第K个叶子节点。
二、算法思想:
1)判断二叉树树是否为完全二叉树,可以采用反证法,当存在一个节点有且只有一个孩子时,则该二叉树不为完全二叉树,否则为完全二叉树。
2)只需要按先序遍历二叉树,当遇到叶子节点就入栈,然后Pop第K个元素即可。
三、核心代码:
int Iscomplete(BiTree T)//判断是否是完全二叉树
{
if(T){//如果存在一个节点的左右孩子有且只有一个,则可判读该树不是完全二叉树
if((T->lchild==0&&T->rchild!=0)||(T->lchild!=0&&T->rchild==0))
return 0;
Iscomplete(T->lchild);
Iscomplete(T->rchild);
}
}
void K_leaf(BiTree T,int k)//输出倒数第K个叶子节点
{
int i;
Stack s;
InitStack(&s);//初始化栈
PreOrderT(T,&s);//将先序遍历二叉树,遇到叶子节点则压栈
for(i=0;i<k-1;i++)
{
Dtop(&s);//删除栈顶元素
}
printf("the value is:%d",Pop(&s));//打印栈顶元素
}
四、完整代码:
#include <stdio.h>
#include<stdlib.h>
#define ElemType int
#define INFINITY 65535 //β值表示无穷大
#define MAXSIZE 1000 //栈的最大空间
//节点声明,数据域、左孩子指针、右孩子指针
typedef struct BiTNode{
int data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//栈的结构声明
typedef struct{
ElemType data[MAXSIZE]; //栈的大小
int top; //栈顶的游标
}Stack;
/*二叉树的有关操作声明*/
BiTree CreateBiTree();//建立一棵二叉树
void PreOrderTraverse(BiTree T);//先序遍历一棵二叉树
int Iscomplete(BiTree T);//判断是否是完全二叉树
void K_leaf(BiTree T,int k);//输出倒数第K个叶子节点
void PreOrderT(BiTree T,Stack*s);//先序遍历一棵二叉树,如果遇到叶子节点则入栈
/*栈的有关操作声明*/
void InitStack(Stack *s); //初始化栈
bool IsEmpty(Stack *s); //判断栈是否为空
ElemType Pop(Stack *s); //返回并删除栈顶的元素
void Push(Stack *s,ElemType e); //将元素e压栈
void Dtop(Stack *s);
/*主函数的实现*/
int main(){
BiTree T;
int k;
printf("请按先序遍历的顺序输入一棵树,以-1表示空\n");
T = CreateBiTree();//建立
PreOrderTraverse(T);//输出
printf("\n");
/*判断是否是二叉树*/
if(Iscomplete(T))
printf("是完全二叉树\n");
else
printf("不是完全二叉树\n");
/*输出倒数第K个叶子节点*/
printf("please input the k:");
scanf("%d",&k);
printf("\n倒数第%d个叶子节点为:",k);
K_leaf(T,k);
return 0;
}
//先序建立二叉树
BiTree CreateBiTree(){
int ch;
BiTree T;
scanf("%d",&ch);
if(ch==-1)
return NULL;
else{
T = (BiTree)malloc(sizeof(BiTNode));//动态申请内存
T->data = ch;
T->lchild = CreateBiTree();
T->rchild = CreateBiTree();
}
return T;//返回根节点
}
//先序遍历二叉树
void PreOrderTraverse(BiTree T){
if(T){
printf("%-3d",T->data);
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
}
int Iscomplete(BiTree T)//判断是否是完全二叉树
{
if(T){//如果存在一个节点的左右孩子有且只有一个,则可判读该树不是完全二叉树
if((T->lchild==0&&T->rchild!=0)||(T->lchild!=0&&T->rchild==0))
return 0;
Iscomplete(T->lchild);
Iscomplete(T->rchild);
}
}
void K_leaf(BiTree T,int k)//输出倒数第K个叶子节点
{
int i;
Stack s;
InitStack(&s);
PreOrderT(T,&s);/*将二叉树按先序遍历的顺序压栈 */
for(i=0;i<k-1;i++)
{
Dtop(&s);
}
printf("the value is:%d",Pop(&s));
}
void PreOrderT(BiTree T,Stack*s)//先序遍历一棵二叉树,并将每一步结果压栈
{
if(T)
{
if(T->lchild==NULL&&T->rchild==NULL)//如果是叶子节点,就入栈
Push(s,T->data);
PreOrderT(T->lchild,s);
PreOrderT(T->rchild,s);
}
}
/*栈的有关实现*/
void InitStack(Stack *s) //初始化栈
{
s->top = -1;
}
bool IsEmpty(Stack *s) //判断栈是否为空
{
if(s->top == -1)
return true;
return false;
}
ElemType Pop(Stack *s) //返回并删除栈顶的元素
{
if(!IsEmpty(s))
return s->data[s->top--];
return INFINITY;
}
void Dtop(Stack *s) //删除栈顶的元素
{
if(!IsEmpty(s))
s->top--;
}
void Push(Stack *s,ElemType e) //将元素压栈
{
if(s->top >= MAXSIZE - 1)
return;
s->top++;
s->data[s->top] = e;
}
五、测试分析: