【数据结构】——树

速通回忆

下面是一个二叉树的演示:包括二叉树的类型构造,二叉树存放一个数值,二叉树的遍历(先序遍历、中序遍历、后序遍历)

你可以选择直接看这个演示代码回忆之前学过的内容,或者看下面的介绍进行二次学习

#include "stdio.h"
#include "stdlib.h"

/* 树的元素结构体,结点元素、左子树、右子树 */
typedef struct tree_n{
    int num;
    struct tree_n *left;
    struct tree_n *right;
} tree_node;

/* 树,根结点 */
typedef struct{
    tree_node *root;
}tree;

/* 树的末尾一个结点 */
void Tree_Insert(tree *t, int nums){
    /* 分配缓存空间 */
    tree_node *node_temp = (tree_node *)malloc(sizeof(tree_node));
    node_temp->num = nums;
    node_temp->left = NULL;
    node_temp->right = NULL;
    
    /* 当树为空的时候 */
    if(t->root == NULL){
        t->root = node_temp;
        return ;
    }
    /* 不为空的时候 */
    tree_node *tree_temp = t->root;
    while(tree_temp){
        /* 比结点小,存放在左子树 */
        if(nums < tree_temp->num){
            /* 当左字数为空的时候 */
            if(tree_temp->left == NULL){
                tree_temp->left = node_temp;
                return ;
            }else{
                tree_temp = tree_temp->left;
            } 
        }
        /*当数值大于等于结点的时候,存放左字数*/
        else{
            /* 当右字数为空的时候 */
            if(tree_temp->right == NULL){
                tree_temp->right = node_temp;
                return ;
            }else{
                tree_temp = tree_temp->right;
            } 
        }
    }
}

/* 中序遍历显示二叉树 */
void TreeShow_infix(tree_node* node){
    if(node){
        TreeShow_infix(node->left);
        printf("%d\t", node->num);
        TreeShow_infix(node->right);
    }
}

/* 先序遍历显示二叉树 */
void TreeShow_pre(tree_node* node){
    if(node){
        printf("%d\t", node->num);
        TreeShow_pre(node->left);
        TreeShow_pre(node->right);
    }
}

/* 后序遍历显示二叉树 */
void TreeShow_epilogue(tree_node* node){
    if(node){
        TreeShow_epilogue(node->left);
        TreeShow_epilogue(node->right);
        printf("%d\t", node->num);
    }
}

int main(){
    /* 创建一棵树 */
    tree tree_temp;
    tree_temp.root = NULL;

    /* 插入一些结点 */
    Tree_Insert(&tree_temp, 5);
    Tree_Insert(&tree_temp, 3);
    Tree_Insert(&tree_temp, 7);
    Tree_Insert(&tree_temp, 2);
    Tree_Insert(&tree_temp, 4);
    Tree_Insert(&tree_temp, 6);
    Tree_Insert(&tree_temp, 8);

    /* 显示树的结构 */
    printf("中序遍历的树的结构:\n");
    TreeShow_infix(tree_temp.root);
    printf("\n\n");

    printf("先序遍历的树的结构:\n");
    TreeShow_pre(tree_temp.root);
    printf("\n\n");

    printf("后序遍历的树的结构:\n");
    TreeShow_epilogue(tree_temp.root);
    printf("\n\n");

    return 0;
}

树的概念

树属于非线性数据结构结构的一种,树的概念是非常多的,下面一一举例。

没有结点的树称为空(null或empty)树。一棵非空的树包括一个根结点,还(很可能)有多个附加结点,所有结点构成一个多级分层结构

树的定义:n个节点组成的有限集合。n=0,空树;n>0,1个根节点,m个互不相交的有限集,每个子集为根的子树。

基本术语

  • 节点的度:树中某个节点的子树(子节点)的个数
  • 树的度:树中各节点的度的最大值
  • 分支节点:度不为0的节点
  • 叶子节点:度为0的节点
  • 路径:i->j
  • 路径:路径经过的节点数-1
  • 孩子节点:节点的后继节点
  • 双亲(父母)节点;该节点为其孩子节点的双亲节点
  • 兄弟节点:同双亲节点的节点
  • 子孙节点:节点的子树的所有节点
  • 祖先节点:从树的根节点到该节点路径上的点
  • 节点层次:根节点为第一层,以此类推
  • 树的高度:树中节点的最大层次
  • 有序树:树中节点按照次序从左向右排序
  • 森林:互不相交的树的集合

树的性值

  • 树的节点树为所有节点的度+1(根节点)
  • 度为m的树中第i层最多有m^(i-1)个节点
  • 高度为h的m层树至多(m^h-1)/(m-1)个节点
  • 具有n个节点的m层树的最小高度为logm( n(m-1) + 1 )  向上取整

二叉树

二叉树是n个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树组成

每一个结点中最多拥有一个左结点和一个右结点,并没有多余的结点,这是很明显的二叉树的特征

二叉树特点

  • 每个结点最多有两棵树
  • 次序不能随意颠倒
  • 要区分左结点和右结点

二叉树性质

  • 二叉树第i层上的结点数目最多为 2的(i-1)次方个节点
  • 深度为k的二叉树至多有2的k次方-1个结点
  • 包含n个结点的二叉树的高度至少为log2 (n+1)、
  • 在任意一颗二叉树中,若终端结点的个数为n0,度为2的结点数为n2,则n0=n2+1

特殊的二叉树

  • 斜树:所有结点都只有左结点或右结点,分别称为左斜树、右斜树
  • 满二叉树:所有的结点都有左结点和右结点,且所有的叶子都在同一层
    • 非叶子结点的度一定为2
    • 叶子结点只能出现在最下面
    • 同一深度,满二叉树是二叉树类中结点树最多,叶子数最多的
  • 完全二叉树:对具有n个结点的二叉树按层编号,如果i结点与同样深度的满二叉树的i结点编号完全相同

二叉树结点设计

二叉树其实就一个每个结点都只允许有左右两个孩子的树

一颗完全二叉树,需要设计:

  • 结点元素
  • 左孩子结点指针
  • 右孩子结点指针
  • 父结点
//树的结点
typedef struct node{
    int data;
    struct node* left;
    struct node* right;
} Node;
  
//树根
typedef struct {
    Node* root;
} Tree;

二叉树的创建

  • 我们创建一个空的结点再进行连接,首先将这个空的结点中的date域赋予数据
  • 判断tree中是否是一个空树如果为空,只需要将整个根指向这一个结点即可
  • 如果不为空,再进行判断:
    • 输入的数据是否大于或者小于当前比对的结点数据,根据其大小进行相应的排列
//创建树--插入数据
void insert(Tree* tree, int value){
    //创建一个节点,让左右指针全部指向空,数据为value
    Node* node=(Node*)malloc(sizeof(Node));
    node->data = value;
    node->left = NULL;
    node->right = NULL;
  
    //判断树是不是空树,如果是,直接让树根指向这一个结点即可
    if (tree->root == NULL){
        tree->root = node;
    } else {//不是空树
        Node* temp = tree->root;//从树根开始
        while (temp != NULL){
            if (value < temp->data){ //小于就进左儿子
                if (temp->left == NULL){
                    temp->left = node;
                    return;
                } else {//继续往下搜寻
                    temp = temp->left;
                }
            } else { //否则进右儿子
                if (temp->right == NULL){
                    temp->right = node;
                    return;
                }
                else {//继续往下搜寻
                    temp = temp->right;
                }
            }
        }
    }
    return;
}

遍历,显示树

遍历分为三种方式:中序遍历、先序遍历、后序遍历,这个前后顺序指的是结点相比其左右子结点排序中的顺序

先序遍历:根左右
中序遍历:左根右
后序遍历:左右根

用C实现三种遍历的代码虽然只有几行,但是一定要搞清楚其中函数回调的意义!!!

先序遍历二叉树

//树的先序遍历 Preorder traversal
void preorder(Node* node){
    if (node != NULL)
    {
        printf("%d ",node->data);
        inorder(node->left);
        inorder(node->right);
    }
}

中序遍历二叉树

//树的中序遍历 In-order traversal
void inorder(Node* node){
    if (node != NULL)
    {
        inorder(node->left);
        printf("%d ",node->data);
        inorder(node->right);
    }
}

后序遍历二叉树

//树的后序遍历 Post-order traversal
void postorder(Node* node){
    if (node != NULL)
    {
        inorder(node->left);
        inorder(node->right);
        printf("%d ",node->data);
    }
}

二叉树森林互相转换

树转换成二叉树

分为3步:

  • 加线:在兄弟(即同一层之间的孩子)之间加一连线
  • 抹线:对每个结点,除了其第一个孩子外,除去其与其余孩子之间的连线
  • 旋转:以树的根结点为轴心,将整树顺时针转45°

旋转之后,结点的左子树还是左子树,最近的兄弟结点变为右子树
注意:树转换成二叉树其右子树一定为空

二叉树转换成树

同样分为3步:

  • 加线:若p结点是双亲结点的左孩子,则将p的右孩子,右孩子的右孩子,……沿分支找到的所有右孩子,都与p的双亲用线连起来
  • 抹线:抹掉原二叉树中双亲与右孩子之间的连线
  • 调整:将结点按层次排列,形成树结构

森林转换成二叉树

  • 将各棵树分别转换成二叉树
  • 将每棵树的根结点用线相连,以第一棵树根结点为二叉树的根
  • 再以根结点为轴心,顺时针旋转,构成二叉树型结构

二叉树转换成森林

  • 抹线:将二叉树中根结点与其右孩子连线,及沿右分支搜索到的所有右孩子间连线全部抹掉,使之变成孤立的二叉树
  • 还原:将孤立的二叉树还原成树(二叉树→树)
如果您觉得这篇文章不错,且手里较为宽裕,可以支持一下博主,一分也是缘分😊
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇