zoukankan      html  css  js  c++  java
  • 数据结构(四)树---二叉树实现

    (一)顺序结构创建二叉树

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    #define OK 1
    #define ERROR 0
    #define TRUE 1
    #define FALSE 0
    
    #define MAXSIZE 100    //存储空间初始分配量
    #define MAX_TREE_SIZE 100    //二叉树的最大结点数
    
    typedef char TElemType;
    typedef int Status;
    
    typedef TElemType SqBiTree[MAX_TREE_SIZE];    //定义顺序二叉树的结构
    
    typedef struct
    {
        int level, order;    //结点的层,本层的序号
    }Position;
    
    TElemType Nil = '^';    //设置结点以^为空
    Status InitBiTree(SqBiTree T);    //构造空二叉树T,因为T是固定数组,不会改变,故不需要&
    Status CreateBiTree(SqBiTree T);//按照层序次序输入二叉树中结点的值,构造顺序存储的二叉树
    Status BiTreeEmpty(SqBiTree T);//判断二叉树是否为空
    int BiTreeDepth(SqBiTree T);//获取二叉树的深度
    Status Root(SqBiTree T, TElemType* e);//返回根节点数据
    TElemType Value(SqBiTree T, Position e);//获取具体位置的结点值
    Status Assign(SqBiTree T, Position e, TElemType value);//对某个叶子结点赋值
    TElemType Parent(SqBiTree T, TElemType e);//根据元素,获取其双亲结点的值
    TElemType LeftChild(SqBiTree T, TElemType e);//返回结点的左孩子
    TElemType RightChild(SqBiTree T, TElemType e);//返回结点的右孩子
    TElemType LeftSibling(SqBiTree T, TElemType e);//返回结点的左兄弟
    TElemType RightSibling(SqBiTree T, TElemType e);//返回结点的右兄弟
    void PreOrderTraverse(SqBiTree T, int e);//开始进行前序遍历
    void InOrderTraverse(SqBiTree T, int e);//开始进行中序遍历
    void PostOrderTraverse(SqBiTree T, int e);//开始进行后序遍历
    void LevelOrderTraverse(SqBiTree T);//开始进行层序遍历
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    #define OK 1
    #define ERROR 0
    #define TRUE 1
    #define FALSE 0
    
    #define MAXSIZE 100    //存储空间初始分配量
    #define MAX_TREE_SIZE 100    //二叉树的最大结点数
    
    typedef char TElemType;
    typedef int Status;
    
    typedef TElemType SqBiTree[MAX_TREE_SIZE];    //定义顺序二叉树的结构
    
    typedef struct
    {
        int level, order;    //结点的层,本层的序号
    }Position;
    
    TElemType Nil = '^';    //设置结点以^为空
    
    
    //构造空二叉树T,因为T是固定数组,不会改变,故不需要&
    Status InitBiTree(SqBiTree T)
    {
        int i;
        for (i = 0; i < MAX_TREE_SIZE; i++)
            T[i] = Nil;
        return OK;
    }
    
    //按照层序次序输入二叉树中结点的值,构造顺序存储的二叉树T
    Status CreateBiTree(SqBiTree T)
    {
        int i = 0;
        char ch;
        printf("please enter value for node(^ is Nil,# exit) number must <= %d:
    ",MAX_TREE_SIZE);
        scanf("%c", &ch);
        while (ch!='#')
        {
            T[i++] = ch;
            if (i != 0 && T[i] != Nil &&T[(i + 1) / 2 - 1] == Nil)    //不为根节点,自己又不为空,父节点又不存在,一定是错的
            {
                printf("exist a node not parents node:%c",T[i]);
                exit(ERROR);
            }
            scanf("%c", &ch);
        }
        //将后面的结点全部置为空:是为了防止使用时创建两次二叉树,出现数据冗余
        while (i<MAX_TREE_SIZE)
        {
            T[i++] = Nil;    //将空值赋给T后面的结点
        }
        return OK;
    }
    
    #define ClearBiTree InitBiTree    //在顺序存储结构中,两者是一致的
    
    //判断二叉树是否为空
    Status BiTreeEmpty(SqBiTree T)
    {
        if (T[0] == Nil)
            return TRUE;
        return FALSE;
    }
    
    //获取二叉树的深度
    int BiTreeDepth(SqBiTree T)
    {
        int i, j=-1;
        for (i = MAX_TREE_SIZE-1; i >= 0; i--)    //获取最后一个结点
            if (T[i] != Nil)
                break;
        //根据pow判断深度
        i++;    //获取从1开始的二叉树,而不是以0开始,方便下面计算
        do 
        {
            j++;
        } while (i>=pow(2,j));
        return j;
    }
    
    //返回根节点数据
    Status Root(SqBiTree T, TElemType* e)
    {
        if (BiTreeEmpty(T))
            return ERROR;
        *e = T[0];
        return OK;
    }
    
    //获取具体位置的结点值
    TElemType Value(SqBiTree T, Position e)
    {
        return T[(int)pow(2,e.level-1)-2+e.order];
    }
    
    //对某个叶子结点赋值
    Status Assign(SqBiTree T, Position e, TElemType value)
    {
        //先将e转换Wie一维数组的下标
        int index = (int)pow(2, e.level - 1) - 2 + e.order;
        //判断其双亲是否存在
        if (index != 0 && T[(index + 1) / 2 - 1] == Nil)
            return ERROR;
        //若是我们赋值为空,但是其子节点存在,也返回空
        if (value == Nil && (T[index * 2 + 1] != Nil || T[index * 2 + 2] != Nil))
            return ERROR;
        T[index] = value;
        return OK;
    }
    
    //根据元素,获取其双亲结点的值
    TElemType Parent(SqBiTree T, TElemType e)
    {
        int i;
        //若是空树
        if (T[0] == Nil)
            return Nil;
        for (i = 1; i < MAX_TREE_SIZE; i++)    //注意这里从1开始,若是出现在头结点,会直接在下面返回Nil
            if (T[i] == e)    //找到该结点
                return T[(i + 1) / 2 - 1];
        return Nil;
    }
    
    //返回结点的左孩子
    TElemType LeftChild(SqBiTree T, TElemType e)
    {
        int i;
        //若是空树
        if (T[0] == Nil)
            return Nil;
        for (i = 1; i < MAX_TREE_SIZE; i++)    //注意这里从1开始,若是出现在头结点,会直接在下面返回Nil
            if (T[i] == e)    //找到该结点
                return T[2*i+1];
        return Nil;
    }
    
    //返回结点的右孩子
    TElemType RightChild(SqBiTree T, TElemType e)
    {
        int i;
        //若是空树
        if (T[0] == Nil)
            return Nil;
        for (i = 1; i < MAX_TREE_SIZE; i++)    //注意这里从1开始,若是出现在头结点,会直接在下面返回Nil
            if (T[i] == e)    //找到该结点
                return T[2 * i + 2];
        return Nil;
    }
    
    //返回结点的左兄弟
    TElemType LeftSibling(SqBiTree T, TElemType e)
    {
        int i;
        //若是空树
        if (T[0] == Nil)
            return Nil;
        for (i = 1; i < MAX_TREE_SIZE; i++)    //注意这里从1开始,若是出现在头结点,会直接在下面返回Nil
            if (T[i] == e&&i%2==0)    //找到右节点
                return T[i-1];
        return Nil;
    }
    
    //返回结点的右兄弟
    TElemType RightSibling(SqBiTree T, TElemType e)
    {
        int i;
        //若是空树
        if (T[0] == Nil)
            return Nil;
        for (i = 1; i < MAX_TREE_SIZE; i++)    //注意这里从1开始,若是出现在头结点,会直接在下面返回Nil
            if (T[i] == e&&i % 2 == 1)    //找到左节点
                return T[i + 1];
        return Nil;
    }
    
    //开始进行前序遍历
    void PreOrderTraverse(SqBiTree T,int e)
    {
        if (T&&e<MAX_TREE_SIZE)
        {
            if (T[e] != Nil)
                printf("%c", T[e]);
            PreOrderTraverse(T, 2 * e + 1);
            PreOrderTraverse(T, 2 * e + 2);
        }
    }
    
    //开始进行中序遍历
    void InOrderTraverse(SqBiTree T, int e)
    {
        if (T&&e<MAX_TREE_SIZE)
        {
            InOrderTraverse(T, 2 * e + 1);
            if (T[e] != Nil)
                printf("%c", T[e]);
            InOrderTraverse(T, 2 * e + 2);
        }
    }
    
    //开始进行后序遍历
    void PostOrderTraverse(SqBiTree T, int e)
    {
        if (T&&e<MAX_TREE_SIZE)
        {
            PostOrderTraverse(T, 2 * e + 1);
            PostOrderTraverse(T, 2 * e + 2);
            if (T[e]!=Nil)
                printf("%c", T[e]);
        }
    }
    
    //开始进行层序遍历
    void LevelOrderTraverse(SqBiTree T)
    {
        int i = MAX_TREE_SIZE - 1;
        int j;
        while (T[i] == Nil)
            i--;
        for (j = 0; j <= i; j++)
            if (T[j] != Nil)
                printf("%c", T[j]);    //值获取非空数据
    }
    函数实现代码
    int main()
    {
        TElemType e;
        Status i;
        Position p; 
        SqBiTree T;
        printf("1.InitBiTree
    ");
        InitBiTree(T);
        printf("2.CreateBiTree
    ");
        CreateBiTree(T);
        printf("3.LevelOrderTraverse
    ");
        LevelOrderTraverse(T);
        printf("
    ");
        printf("4.PreOrderTraverse
    ");
        PreOrderTraverse(T,0);
        printf("
    ");
        printf("5.InOrderTraverse
    ");
        InOrderTraverse(T,0);
        printf("
    ");
        printf("6.PostOrderTraverse
    ");
        PostOrderTraverse(T, 0);
        printf("
    ");
        printf("7.PostOrderTraverse
    ");
        if (Root(T, &e))
            printf("8.Root:%d
    ", e);
        printf("9.PostOrderTraverse
    ");
        printf("10.LeftChild for D --> %c
    ", LeftChild(T, 'D'));
        printf("11.RightChild for D --> %c
    ", RightChild(T, 'D'));
        printf("12.LeftSibling for H --> %c
    ", LeftSibling(T, 'H'));
        printf("13.RightSibling for G --> %c
    ", RightSibling(T, 'G'));
        printf("14.BiTreeDepth:%d
    ", BiTreeDepth(T));
        p.level = 4;
        p.order = 2;
        printf("15.Value row4 col2:Z
    ");
        Assign(T, p, 'Z');
        LevelOrderTraverse(T);
    
        system("pause");
        return 0;
    }
    main函数测试

    (二)链式结构创建二叉树

    //按照前序输入二叉树中结点的值(一个字符)
    //#表示空树,构造二叉树表表示二叉树T
    void CreateBiTree(BiTree *T)
    {
        TElemType ch;
        scanf("%c", &ch);
        if (ch == '#')
            *T = NULL;
        else
        {
            *T = (BiTree)malloc(sizeof(BiTNode));
            if (!*T)
                exit(ERROR);
            (*T)->data = ch;    //生成根节点数据
            CreateBiTree(&(*T)->lchild);    //构造左子树
            CreateBiTree(&(*T)->rchild);    //构造右子树
        }
    }

    (三)使用递归实现对二叉树的遍历

    #include <stdio.h>
    #include <stdlib.h>
    
    #define OK 1
    #define ERROR 0
    #define TRUE 1
    #define FALSE 0
    
    #ifndef BINTREE_H
    #define BINTREE_H
    typedef char TElemType;
    typedef int Status;
    
    //二叉树的二叉链表结点结构定义
    typedef struct BiTNode    //结点结构
    {
        TElemType data;    //结点数据
        struct BiTNode *lchild, *rchild;    //左右孩子指针
    }BiTNode, *BiTree;
    #endif
    BinT.h
    #define _CRT_SECURE_NO_WARNINGS
    #include "BinT.h"
    void PreOrderTraverse(BiTree T, int level)
    {
        if (T)
        {
            printf("%c in level %d
    ", T->data,level + 1);
            PreOrderTraverse(T->lchild, level + 1);
            PreOrderTraverse(T->rchild, level + 1);
        }
    }
    
    void InOrderTraverse(BiTree T, int level)
    {
        if (T)
        {
            InOrderTraverse(T->lchild, level + 1);
            printf("%c in level %d
    ", T->data, level + 1);
            InOrderTraverse(T->rchild, level + 1);
        }
    }
    
    
    void PostOrderTraverse(BiTree T, int level)
    {
        if (T)
        {
            PostOrderTraverse(T->lchild, level + 1);
            PostOrderTraverse(T->rchild, level + 1);
            printf("%c in level %d
    ", T->data, level + 1);
        }
    }
    
    
    int main()
    {
        BiTree T;
        printf("1.CreateBiTree
    ");
        CreateBiTree(&T);
        printf("2.PreOrderTraverse
    ");
        PreOrderTraverse(T, 0);
        printf("3.InOrderTraverse
    ");
        InOrderTraverse(T, 0);
        printf("4.PostOrderTraverse
    ");
        PostOrderTraverse(T, 0);
        
        system("pause");
        return 0;
    }

    (四).使用栈实现非递归,遍历二叉树

    #include <stdio.h>
    #include <stdlib.h>
    #include "BinT.h"
    
    #define OK 1
    #define ERROR 0
    #define TRUE 1
    #define FALSE 0
    
    #define MAXSIZE 100
    
    typedef BiTree ElemType;
    
    typedef struct
    {
        ElemType data[MAXSIZE];
        int top;
    }sqStack;
    
    Status InitStack(sqStack *s);    //初始化操作,建立一个空栈
    Status ClearStack(sqStack *s);    //将栈清空
    Status StackEmpty(sqStack s);    //若栈存在,返回true,否则返回false
    
    Status Push(sqStack *s, ElemType e);    // 若是栈存在,则插入新的元素e到栈S中并成为栈顶元素
    Status Pop(sqStack *s, ElemType *e);    //若是栈存在且非空,删除栈顶元素,并用e返回其值
    stack.h
    #define _CRT_SECURE_NO_WARNINGS
    #include "stack.h"
    
    //初始化操作,建立一个空栈
    Status InitStack(sqStack *s)
    {
        if (!s)
            return ERROR;
        memset(s->data, 0, MAXSIZE*sizeof(ElemType));
        s->top = -1;
        return OK;
    }
    
    //将栈清空
    Status ClearStack(sqStack *s)
    {
        if (!s)
            return ERROR;
        s->top = -1;
        return OK;
    }
    
    //若栈存在,返回true,否则返回false
    Status StackEmpty(sqStack s)
    {
        if (s.top == -1)
            return OK;
        return ERROR;
    }
    
    // 若是栈存在,则插入新的元素e到栈S中并成为栈顶元素
    Status Push(sqStack *s, ElemType e)
    {
        if (s->top == MAXSIZE||!s)
            return ERROR;
        s->top++;
        s->data[s->top] = e;
        return OK;
    }
    
    //若是栈存在且非空,删除栈顶元素,并用e返回其值
    Status Pop(sqStack *s, ElemType *e)
    {
        if (!s || StackEmpty(*s) || !e)
            return ERROR;
        *e = s->data[s->top--];
        return OK;
    }
    stack.c使用顺序栈
    void PreOrderTraverseByStack(BiTree BT)
    {
        BiTree T = BT;
        sqStack s;
        InitStack(&s);
        while (T || !StackEmpty(s))
        {
            while (T)
            {
                printf("%c", T->data);
                Push(&s, T);
                T = T->lchild;
            }
            if (!StackEmpty(s))
            {
                Pop(&s, &T);
                T = T->rchild;
            }
        }
        printf("
    ");
    }
    
    void InOrderTraverseByStack(BiTree BT)
    {
        BiTree T = BT;
        sqStack s;
        InitStack(&s);
        while (T || !StackEmpty(s))
        {
            while (T)
            {
                Push(&s, T);
                T = T->lchild;
            }
            if (!StackEmpty(s))
            {
                Pop(&s, &T);
                printf("%c", T->data);
                T = T->rchild;
            }
        }
        printf("
    ");
    }
    void PostOrderTraverseByStack(BiTree BT)
    {
        BiTree T = BT;
        sqStack s;
        InitStack(&s);
        while (T||!StackEmpty(s))
        {
            while (T)
            {
                Push(&s, T);
                T = T->lchild;
            }
            if (!StackEmpty(s))
            {
                Pop(&s, &T);
                if (!T->rchild||T->first==2)
                {
                    printf("%c", T->data);
                    T = NULL;
                }
                else
                {
                    T->first = 2;
                    Push(&s,T);
                    T = T->rchild;
                }
            }
        }
        printf("
    ");
    }
    //二叉树的二叉链表结点结构定义
    typedef struct BiTNode    //结点结构
    {
        TElemType data;    //结点数据
        int first;    //对于非递归后序而言
        struct BiTNode *lchild, *rchild;    //左右孩子指针
    }BiTNode, *BiTree;
    注意:针对后序非递归遍历,我们需要为结点设置一个标识
    int main()
    {
        BiTree T;
        printf("1.CreateBiTree
    ");
        CreateBiTree(&T);
        printf("2.PreOrderTraverse
    ");
        PreOrderTraverse(T, 0);
        printf("3.InOrderTraverse
    ");
        InOrderTraverse(T, 0);
        printf("4.PostOrderTraverse
    ");
        PostOrderTraverse(T, 0);
        printf("5.PreOrderTraverseByStack
    ");
        PreOrderTraverseByStack(T);
        printf("6.InOrderTraverseByStack
    ");
        InOrderTraverseByStack(T);
        printf("7.PostOrderTraverseByStack
    ");
        PostOrderTraverseByStack(T);
        
        system("pause");
        return 0;
    }

    (五)使用队列完成层序遍历

    #include <stdio.h>
    #include <stdlib.h>
    #include "BinT.h"
    
    #define OK 1
    #define ERROR 0
    #define TRUE 1
    #define FALSE 0
    
    typedef BiTree ElemType;
    typedef int Status;
    
    //设置队列的数据结点
    typedef struct QNode
    {
        ElemType data;    //存放队列中的数据
        struct QNode* next;    //队列结点的指针域
    }QNode, *QNodePtr;
    
    //设置队列的结构体
    typedef struct
    {
        QNodePtr front, rear;    //队列头尾指针
    }LinkQueue;
    
    //四个基础操作
    Status InitQueue(LinkQueue *Q);    //初始化操作,建立一个空队列Q
    Status ClearQueue(LinkQueue *Q);//将队列清空
    Status QueueEmpty(LinkQueue Q);    //若队列为空,返回true,否则返回false
    
    Status EnQueue(LinkQueue *Q, ElemType e);    //若是队列存在,则插入新的元素e入队为队尾
    Status DeQueue(LinkQueue *Q, ElemType *e);    //若是队列存在且非空,进行出队操作,用e接收数据
    queue.h
    #include "queue.h"
    
    //初始化操作,建立一个空队列Q
    Status InitQueue(LinkQueue *Q)
    {
        if (!Q)
            return ERROR;
        Q->front = Q->rear = (QNodePtr)malloc(sizeof(QNode));
        if (!Q->front)
            return ERROR;
        Q->front->next = Q->rear->next = NULL;
        return OK;
    }
    
    
    //将队列清空,保留头结点,注意队尾指针
    Status ClearQueue(LinkQueue *Q)
    {
        QNodePtr head = Q->front->next;    //获取开始结点
        QNodePtr cur;    //游标指针
        if (!Q)
            return ERROR;
        while (head)    //将数据全部释放
        {
            cur = head;
            head = head->next;
            free(cur);
        }
        Q->rear = Q->front;    //将队尾指向队头
        Q->rear->next = Q->front->next = NULL;    //记得:重点
        return OK;
    }
    
    
    //若队列为空,返回true,否则返回false
    Status QueueEmpty(LinkQueue Q)
    {
        if (!Q.front->next)
            return TRUE;
        return FALSE;
    }
    
    
    //若是队列存在,则插入新的元素e入队为队尾,注意还要考虑队尾指针
    Status EnQueue(LinkQueue *Q, ElemType e)
    {
        if (!Q)
            return ERROR;
        QNodePtr q = (QNodePtr)malloc(sizeof(QNode));
        if (!q)
            return ERROR;
        q->data = e;
        q->next = Q->rear->next;
        Q->rear->next = q;
        Q->rear = q;
        return OK;
    }
    
    //若是队列存在且非空,进行出队操作,用e接收数据,注意还要考虑队尾指针
    Status DeQueue(LinkQueue *Q, ElemType *e)
    {
        QNodePtr q;
        if (!Q || !e || QueueEmpty(*Q))
            return ERROR;
        q = Q->front->next;    //开始结点
        *e = q->data;
        Q->front->next = q->next;    //指针后移(这一步注意:重点,且易错)
        if (Q->rear == q)    //若是我们队列中只有一个结点,删除后需要修改队尾指针
            Q->rear = Q->front;
        free(q);    //释放结点
        return OK;
    }
    queue.c
    void LevelOrderTraverseByQueue(BiTree T)
    {
        LinkQueue Q;
        BiTree Tmp;
        InitQueue(&Q);
        if (!T)
            return ;
        EnQueue(&Q, T);
        while (!QueueEmpty(Q))
        {
            DeQueue(&Q, &Tmp);
            printf("%c", Tmp->data);
            if (Tmp->lchild)
                EnQueue(&Q, Tmp->lchild);
            if (Tmp->rchild)
                EnQueue(&Q, Tmp->rchild);
        }
        printf("
    ");
    }

  • 相关阅读:
    Maximum Flow Exhaustion of Paths Algorithm
    ubuntu下安装java环境
    visualbox使用(二)
    vxworks一个超级奇怪的错误(parse error before `char')
    February 4th, 2018 Week 6th Sunday
    February 3rd, 2018 Week 5th Saturday
    February 2nd, 2018 Week 5th Friday
    February 1st, 2018 Week 5th Thursday
    January 31st, 2018 Week 05th Wednesday
    January 30th, 2018 Week 05th Tuesday
  • 原文地址:https://www.cnblogs.com/ssyfj/p/9463922.html
Copyright © 2011-2022 走看看