数据结构--基于天勤--二叉树

/*
树
2018.12.20
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define element char
#define MAXSIZE 1000
                                                                                                                 
typedef struct BinaryTreeNode
{
    element data;
    struct BinaryTreeNode *leftChild;
    struct BinaryTreeNode *rightChild;
}BinaryTreeNode;

 

//创建二叉树(先序创建)
BinaryTreeNode *preCreate()
{
    element input;
    BinaryTreeNode *p;
 
    //这里直接 %c前面加空格就好了,这样无论怎么输入(空多少格)都没有问题
    scanf(" %c", &input);    //这样调用scanf时,树的结点一次全部输入,如果要一次一个的输入,在%c前加个空格
    if (input != '*')
    {
        p = (BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));
        p->data = input;
        p->leftChild = preCreate();
        p->rightChild = preCreate();
    }
    else
    {
        p = NULL;//如果输入的是 '*'
    }
    return p;
}

 

//前序遍历(递归实现)
/*
算法思想:
如果当前结点不为空
    访问当前结点
    前序遍历左子树
    前序遍历右子树
*/
void preorder(BinaryTreeNode *p)
{
    if (p != NULL)
    {
        printf("%c", p->data);//遍历操作,此处为打印数据元素
        preorder(p->leftChild);
        preorder(p->rightChild);
    }
}
 
//中序遍历(递归实现)
/*
算法思想:
如果当前结点不为空
    中序遍历左子树
    访问当前结点
    中序遍历右子树
*/
void inorder(BinaryTreeNode *p)
{
    if (p != NULL)
    {
        inorder(p->leftChild);
        printf("%c", p->data);
        inorder(p->rightChild);
    }
}
 
//后序遍历(递归实现)
/*
算法思想:
如果当前结点不为空
    后序遍历左子树
    后序遍历右子树
    访问当前结点
*/
void postorder(BinaryTreeNode *p)
{
    if (p != NULL)
    {
        postorder(p->leftChild);
        postorder(p->rightChild);
        printf("%c", p->data);
    }
}

 

//层次遍历(循环队列)
/*
  算法思想:
  定义结点队列
  如果当前结点不为空   //不是空树
        根节点入队     //循环队列
        while(队列非空)出队打印,左孩子入队之后,右孩子入队;
*/
void levelorder(BinaryTreeNode *p)
{
    int front, rear;
    front = rear = 0;
    BinaryTreeNode *que[MAXSIZE];//    队列的简单定义,队列存放的是二叉树结点的地址
 
    BinaryTreeNode *temp;
    if (p != NULL)//当结点非空
    {
        rear = (rear + 1) % MAXSIZE;
        que[rear] = p;//根节点入队
 
        while (front != rear)//当队列非空
        {
            front = (front + 1) % MAXSIZE;
            temp = que[front];//队头结点出队
            printf("%c", temp->data);
 
            if (temp->leftChild != NULL)//存在队头结点的左孩子,左孩子入队
            {
                rear = (rear + 1) % MAXSIZE;
                que[rear] = temp->leftChild;
            }
 
            if (temp->rightChild != NULL)//存在队头结点的右孩子,右孩子入队
            {
                rear = (rear + 1) % MAXSIZE;
                que[rear] = temp->rightChild;
            }
        }
    }
}

 

//获取树高(递归实现)
/*
算法思想:
定义左子树高度、右子树高度
如果当前结点为空,返回0
否则 求左子树高度
     求右子树高度
     返回较高子树的高度+1  //加1是因为根节点
*/
int getDepth(BinaryTreeNode *p)
{
    int leftDepth, rightDepth;
    if (p == NULL)return 0;
    else
    {
        leftDepth = getDepth(p->leftChild);
        rightDepth = getDepth(p->rightChild);
        return (leftDepth > rightDepth ? leftDepth : rightDepth) + 1;
    }
}

 

//获取叶子(递归实现)
/*
算法思想:
如果当前结点不为空
    如果左子树和右子树都不存在,打印数据
    获取左子树的叶子
    获取右子树的叶子
*/
void getLeaf(BinaryTreeNode *p)
{
    if (p != NULL)
    {
        if (p->leftChild == NULL && p->rightChild == NULL)
            printf("%c", p->data);
        getLeaf(p->leftChild);
        getLeaf(p->rightChild);
 
    }
 
}

 

//前序遍历(非递归实现/自定义栈)
/*
算法思想:
如果根节点不为空
    初始化栈,存储结点
    根节点入栈
    当栈不空:出栈打印,右孩子入栈之后,左孩子入栈
*/
void preorderNonRecursion(BinaryTreeNode *bt)
{
    if (bt != NULL)
    {
        BinaryTreeNode *stack[MAXSIZE];
        int top = -1;//初始化栈
 
        BinaryTreeNode *p = NULL;
 
        stack[++top] = bt;//根结点入栈
        while (top != -1 )
        {
            p = stack[top--];//出栈
            printf("%c", p->data);//打印
 
            if (p->rightChild != NULL)//右孩子先入栈
                stack[++top] = p->rightChild;
            if (p->leftChild != NULL)//左孩子后入栈
                stack[++top] = p->leftChild;
        }
    }
}

 

//中序遍历(非递归实现/自定义栈)
/*
算法思想:
如果根节点不为空
    初始化栈,存储结点
    当栈非空 或 结点非空
        当结点非空:入栈读左子 //一直读到底
        如果栈非空:出栈打印读右子
*/
void inorderNonRecursion(BinaryTreeNode *bt)
{
    if (bt!= NULL)
    {
        BinaryTreeNode *stack[MAXSIZE];
        int top = -1;//栈初始化
 
        BinaryTreeNode *p;
        p = bt;
 
        while (top != -1 || p != NULL)//当读取根节点的右子树时,栈空top = -1
        {                                //但此时 temp = 根->rightChild   != NULL
            while (p != NULL)
            {
                stack[++top] = p;
                p = p->leftChild;
            }
            
            if (top != -1)
            {
                p = stack[top--];
                printf("%c", p->data);
                p = p->rightChild;
            }
        }
 
 
    }
}

 

//后序遍历(非递归实现/自定双栈)
/*
算法思想:
如果根结点不为空
    定义双栈
    根节点入栈1
    当栈1非空:栈1出栈入栈2,左子非空入栈1,右子非空入栈1  //入栈1的顺序与前序遍历非递归相反  逆后序遍历序列
    当栈2非空:栈2出栈得后序遍历顺序                       // 前序遍历非递归为先入栈右子,后入栈左子
*/
void postorderNonRecursion(BinaryTreeNode *bt)
{
    if (bt != NULL)//树非空
    {
        //双栈的定义
        BinaryTreeNode *stack1[MAXSIZE]; int top1 = -1;
        BinaryTreeNode *stack2[MAXSIZE]; int top2 = -1;
 
        BinaryTreeNode *p = NULL;
        stack1[++top1] = bt;
 
        while (top1 != -1)//stack1辅助建立逆后序遍历序列,逆后序遍历序列全部入栈stack2
        {
            p = stack1[top1--];
            stack2[++top2] = p;
 
            if (p->leftChild != NULL)
                stack1[++top1] = p->leftChild;
            if (p->rightChild != NULL)
                stack1[++top1] = p->rightChild;
        }
 
        while (top2 != -1)//stack2中的逆后序遍历序列出栈,得到后序遍历顺序
        {
            p = stack2[top2--];
            printf("%c", p->data);
        }
 
 
 
    }
}

 

int main()
{
    /*
    输入序列:
    ABD*G***CE**FH***
    */
 
    BinaryTreeNode *p = preCreate();
    printf("\n前序遍历:"); preorder(p);
    printf("\n中序遍历:"); inorder(p);
    printf("\n后序遍历:"); postorder(p);
    printf("\n层次遍历:"); levelorder(p);
    printf("\n树的高度:%d",getDepth(p)); 
    printf("\n树的叶子:"); getLeaf(p);
    printf("\n【非递归实现/自定义栈】前序遍历:"); preorderNonRecursion(p);
    printf("\n【非递归实现/自定义栈】中序遍历:"); inorderNonRecursion(p);
    printf("\n【非递归实现/自定双栈】后序遍历:"); postorderNonRecursion(p);
 
    return 0;
}


 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值