数据结构之二叉树


  1. 树是有 n 个节点的有限集合,它满足下面的两个条件:① 有且仅有一个特定的称为根的节点;② 其余的节点可分为 m 个互不相交的有限集合,其中每一个集合也是一棵树

  2. 相关概念
    节点度:一个节点子树的个数
    树的度:一棵树中节点度的最大值
    叶子:度数为0的节点
    内部节点:除了根节点之外的节点
    双亲:某个节点的上一层节点
    兄弟:同意双亲的孩子
    祖先:从A节点到B节点有路径,则A是B的祖先
    高度:树中节点的最大层次称为树的高度
    森林:n棵互不相交的树

  3. 二叉树
    每个节点最多只有两棵子树,有左右之分不能颠倒,特殊形态有满二叉树和完全二叉树

  4. 存储方式
    二叉树的存储方式分为顺序存储结构和链式存储结构。顺序存储结构是指用一维数组存储二叉树中的节点,并且节点的存储位置能体现节点之间的父子关系,缺点是会造成存储空间的浪费;链式存储结构可以分成两种,一种是二叉链存储方式,另一种是三叉链存储方式,二叉链包含左节点和右节点,三叉链包含左子节点、右子节点和父节点。

  5. 基本操作代码

#include <stdio.h> 
#include <stdlib.h> 

#define QUEUE_MAXSIZE 50

// 定义二叉树中的元素类型
typedef char DATA;

// 定义二叉树中的节点类型
typedef struct Node {
    // 元素
    DATA element;
    // 左子树
    struct Node *leftChild;
    // 右子树
    struct Node *rightChild;
} BinaryTree;

// 初始化二叉树根节点
BinaryTree *init(BinaryTree *root) {
    // 若二叉树根节点不为空
    if(root !=NULL)
        return root ;
    root = (BinaryTree *) malloc(sizeof(BinaryTree));
    return root;
}

/**
 * 向二叉树中的节点添加孩子节点
 * @param parent:父亲节点
 * @param node :要添加的节点
 * @param n :添加的位置,1表示左节点,2表示右节点
 * @return
 */
int addNode(BinaryTree *parent, BinaryTree *node, int n) {
    if (parent == NULL) {
        printf("父亲节点不存在,添加失败");
        return 0;
    }
    switch (n) {
        case 1:
            // 添加到左节点
            if (parent->leftChild) {
                // 左节点不为空
                printf("左节点不为空,添加失败");
                return 0;
            } else
                parent->leftChild = node;
            break;

        case 2:
            // 添加到右节点
            if (parent->rightChild) {
                // 右节点不为空
                printf("右节点不为空,添加失败");
                return 0;
            } else
                parent->rightChild = node;
            break;

        default:
            printf("输入参数错误");
            return 0;
    }
    return 1;
}

/**
 * 获得父亲节点的左子节点
 * @param parent :父亲节点
 * @return :返回子节点的元素值,不存在返回NULL
 */
DATA getLeft(BinaryTree *parent) {
    if (parent->leftChild)
        return parent->leftChild->element;
    else
        return NULL;
}

/**
 * 获得父亲节点的右子节点
 * @param parent :父亲节点
 * @return :返回子节点的元素值,不存在返回NULL
 */
DATA getRight(BinaryTree *parent) {
    if (parent->rightChild)
        return parent->rightChild->element;
    else
        return NULL;
}

/**
 * 判空
 * @param root:二叉树节点
 * @return
 */
int isEmpty(BinaryTree *root) {
    if (root)
        return 0;
    else
        return 1;
}

/**
 * 求二叉树的深度
 * @param root
 * @return 递归遍历左子树和右子树,取最大值
 */
int deepth(BinaryTree *root) {
    int dep1, dep2;
    if (root == NULL)
        return 0; //对于空树,深度为0
    else {
        dep1 = deepth(root->leftChild);
        dep2 = deepth(root->rightChild);
        if (dep1 > dep2)
            return dep1 + 1;
        else
            return dep2 + 1;
    }
}

/**
 * 查找二叉树中是否包含某元素
 * @param root :二叉树的根节点
 * @param data :要查找的数据
 * @return :1包含,0不包含
 */
int search(BinaryTree *root, DATA data) {
    if (root == NULL)
        return 0;
    else {
        if (root->element == data)
            return 1;
        else {
            if (search(root->leftChild, data) == 1)
                return 1;
            else if (search(root->rightChild, data) == 1)
                return 1;
            else
                return 0;
        }
    }
}

void clear(BinaryTree *root) {
    if (root) {
        clear(root->leftChild);
        clear(root->rightChild);
        free(root);
        root = NULL;
    }
    return;
}

/**
 * 前序遍历
 * @param root
 */
void preOrder(BinaryTree *root) {
    if (root) {
        printf("%c、", root->element);
        preOrder(root->leftChild);
        preOrder(root->rightChild);
    }
    return;
}

/**
 * 中序遍历
 * @param root
 */
void inOrder(BinaryTree *root) {
    if (root) {
        inOrder(root->leftChild);
        printf("%c、", root->element);
        inOrder(root->rightChild);
    }
    return;
}

/**
 * 后序遍历
 * @param root
 */
void postOrder(BinaryTree *root) {
    if (root) {
        postOrder(root->leftChild);
        postOrder(root->rightChild);
        printf("%c、", root->element);
    }
    return;
}

/**
 * 按层遍历
 * @param root
 */
void levelOrder(BinaryTree *root) //按层遍历
{
    BinaryTree *p;
    BinaryTree *q[QUEUE_MAXSIZE]; //定义一个顺序栈
    int head = 0, tail = 0;//队首、队尾序号
    if (root)//若队首指针不为空
    {
        tail = (tail + 1) % QUEUE_MAXSIZE;//计算循环队列队尾序号
        q[tail] = root;//将二叉树根指针进队
    }
    while (head != tail) //队列不为空,进行循环
    {
        head = (head + 1) % QUEUE_MAXSIZE; //计算循环队列的队首序号
        p = q[head]; //获取队首元素
        printf("%c、", root->element);//处理队首元素
        if (p->leftChild != NULL) //若节点存在左子树,则左子树指针进队
        {
            tail = (tail + 1) % QUEUE_MAXSIZE;//计算循环队列的队尾序号
            q[tail] = p->leftChild;//将左子树指针进队
        }

        if (p->rightChild != NULL)//若节点存在右孩子,则右孩子节点指针进队
        {
            tail = (tail + 1) % QUEUE_MAXSIZE;//计算循环队列的队尾序号
            q[tail] = p->rightChild;//将右子树指针进队
        }
    }
    return;
}

int main() {

    BinaryTree *root=NULL;
    root = init(root);

    root->element = 'A';
    root->leftChild = NULL;
    root->rightChild = NULL;

    BinaryTree *temp = NULL;
    temp = init(temp);

    temp->element = 'A' + 1;
    temp->rightChild = NULL;
    temp->leftChild = NULL;

    addNode(root, temp, 1);

    printf("根节点的左子树和右子树分别是:%c,%c\n",getLeft(root),getRight(root));
    preOrder(root);

    printf("\n树的高度是:%d",deepth(root));
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值