C语言|数据结构——树的定义、存储与遍历

简介: 基本概念定义:1.有且只有一个称为根的节点; 2.有若干个互不相交的子树,这些子树本身也是一棵树; 3.由节点和边组组成的; 4.每个节点只有一个父节点,可以有无数个子节点(除了根节点)。分类:|一般树。任意一个子节点个数不受限制,可以是有序树也可以是无序树。|二叉树。任意一个节点最大度为2,二叉树是有序树,左右节点不能随意互换。 | 一般二叉树 |满二叉树。每一层节点都是满的。 |完全二叉树。除最后一层外,每一层节点都是满的,最后一层节点一定从左向右连续排列。|森林。n个互不相交的树的集合,可以是互不相连的几个树一些专业术语:父节

基本概念

定义:

1.有且只有一个称为根的节点;  

2.有若干个互不相交的子树,这些子树本身也是一棵树;  

3.由节点和边组组成的;  

4.每个节点只有一个父节点,可以有无数个子节点(除了根节点)。

分类:

|一般树。任意一个子节点个数不受限制,可以是有序树也可以是无序树。

|二叉树。任意一个节点最大度为2,二叉树是有序树,左右节点不能随意互换。

    | 一般二叉树

    |满二叉树。每一层节点都是满的。

    |完全二叉树。除最后一层外,每一层节点都是满的,最后一层节点一定从左向右连续排列。

|森林。n个互不相交的树的集合,可以是互不相连的几个树

一些专业术语:

父节点:该节点上面紧挨着的一个节点,一个节点只有一个父节点。

祖先节点:一个节点的父节点的父节点,一个节点只有一个。

兄弟节点:两个节点具有共同的父节点。

堂兄弟节点:两个节点的父节点不同,但各自的父节点彼此是兄弟节点。

子孙节点:一个节点的所有子节点和子孙节点。

树的深度:从根节点到最底层节点的层数,根节点是第一层。

叶子节点:没有子节点的节点。

非终端节点:非叶子节点。

度:子结点的个数称为度。

最大的度:一个树中含有最大度的那个度是这个树最大的度。

树的存储

本质是把非线性结构转化成线性结构进行存储。任何树的存储都是先转化成二叉树之后再按照二叉树的方式进行存储。

二叉树的存储

    |连续存储(只能以完全二叉树形式存储)

    |链式存储

一般树的存储

双亲表示法

*利用结构体数组存储

*数组下表即为该节点编号,结构体内部有两部分,一部分是数据域,一部分存储其父节点编号,如果没有父节点则为-1。

*缺点是只能记录无序树。

孩子表示法

*数组结构体

*每个节点由两部分组成,一部分是数据域,一部分存储其子节点的地址,所有孩子像链表一样连起来。后面的子节点是无序的。

*缺点是难以寻找父节点。

双亲孩子表示法

*数组结构体

*每个节点对应的数组下标就是各自的编号。每个节点由三部分组成:数据域,父节点下标,孩子节点地址。

*优势:即方便找父节点也方便找孩子节点。

二叉树表示法(最常用)

*结构体数组

*思路是先转化为二叉树,再按照二叉树的方法进行存储。每个节点有3个部分组成:一个数据域,一个指向其最左侧第一个孩子,另一个指针域指向其第一个兄弟。这一步可以把一个普通树转化为一个二叉树,这个过程也可以通过画图形象的表示出来。

*普通树转化成二叉树一定没有右子树。

森林的存储

*把森林转化成二叉树。 把根节点互相看做兄弟,接下来转化方法就跟普通树一样。

树的遍历

先序遍历,中序遍历,后序遍历这三种方法有一些共同之处:每遍历到一个节点,这个节点本身就可以看做是又一棵树的根节点。

先序遍历

根节点->先序访问左子树->先序访问右子树

下图遍历顺序:① -> ② -> ④ -> ⑤ -> ③ -> ⑥ -> ⑦

描述:先遍历根节点①;接着来到左孩子②,②这棵树仍然存在左孩子④,所以来到④;④是叶子结点,是一棵空树,左右节点都不存在,所以④这棵树遍历完成,也代表着②的左子树遍历完成;②的左子树遍历完成后,接下来来到其右孩子⑤,⑤的遍历方法和④一样;②的左右节点都遍历完成,②这棵树就遍历完成了,也就是①的左子树遍历完成;接下来以相同的方法遍历①的右子树③,大家自行推断。

        ①


       /    \


    ②     ③


    / \      / \


 ④ ⑤ ⑥ ⑦


中序遍历

左子树->根节点->先序访问右子树

上图遍历顺序:④ -> ② -> ⑤ -> ① -> ⑥ -> ③ -> ⑦

描述:根节点①的左孩子是②,②仍然有左孩子④,直到④才没有左孩子,所以④的左子树可以认为已经遍历完成,然后遍历空树④的根节点④,其右子树也不存在所以也可以认为遍历完成;④遍历完成,即②的左子树遍历完成,接着遍历②的根节点②,接着以同样的操作遍历⑤;②遍历完成,即①的左子树遍历完成,接着以同样的方法遍历其右子树③,请大家自行脑补。

后序遍历

后序遍历左子树->后序遍历右子树->根节点

上图遍历顺序:④ -> ⑤ -> ② -> ⑥ -> ⑦ -> ③ -> ①

描述:下面我只描述一下如何遍历①的右子树。记得我们上面说的吗,“每遍历到一个节点,这个节点本身就可以看做是又一棵树的根节点”,现在我们就把③看作是一棵树的根节点,所以要先遍历其左子树⑥,再遍历其右子树⑦,最后遍历根节点③。

层序遍历

从上往下,从左往右挨个遍历。

上图遍历顺序:① -> ② -> ③ -> ④ -> ⑤ -> ⑥ -> ⑦

#include <stdio.h>#include <stdlib.h> typedefstructT{
intdata;
structT*left;
structT*right;
}T,*PT;
//使用递归的方法创建一个树 PTmake()
{
intdata;
scanf("%d",&data);
getchar();//吸收scanf的回车键 //判断数据,如果是-1,那么不创建该节点并且向上返回//如果不是-1,那么就创建该节点并且把该数字存储到数据域 if(data==-1)
returnNULL;
else    {
PTtree=(PT)malloc(sizeof(T));
tree->data=data;
printf("请输入节点%d的左子树",data);
tree->left=make();
printf("请输入节点%d的右子树",data);
tree->right=make();
returntree;
    }
}
//先序遍历 :根-左-右 voidxianxu(PTtree)
{
//判断树是否为空 if(tree==NULL)
return;
else    {
printf("%d",tree->data); 
xianxu(tree->left);
xianxu(tree->right); 
    }
} 
//中序遍历:左-根-右 voidzhongxu(PTtree)
{
if(tree==NULL)
return;
else    {
xianxu(tree->left);
printf("%d",tree->data); 
xianxu(tree->right); 
    }
}
//后序遍历:左-右-根 voidhouxu(PTtree)
{
if(tree==NULL)
return;
else    {
xianxu(tree->left);
xianxu(tree->right); 
printf("%d",tree->data); 
    }
}
intmain()
{
printf("创建一棵树,请输入根节点");
PTtree=make();
intchoose;
printf("先序遍历请按1;中序遍历请按2;后序遍历请按3:\n");
scanf("%d",&choose);
getchar();
switch(choose)
    {
case1:xianxu(tree);
break;
case2:zhongxu(tree);
break;
case3:houxu(tree);
break;
default:
break;
    }
 } 


相关文章
|
8天前
|
存储 人工智能 C语言
数据结构基础详解(C语言): 栈的括号匹配(实战)与栈的表达式求值&&特殊矩阵的压缩存储
本文首先介绍了栈的应用之一——括号匹配,利用栈的特性实现左右括号的匹配检测。接着详细描述了南京理工大学的一道编程题,要求判断输入字符串中的括号是否正确匹配,并给出了完整的代码示例。此外,还探讨了栈在表达式求值中的应用,包括中缀、后缀和前缀表达式的转换与计算方法。最后,文章介绍了矩阵的压缩存储技术,涵盖对称矩阵、三角矩阵及稀疏矩阵的不同压缩存储策略,提高存储效率。
|
8天前
|
C语言
数据结构基础详解(C语言):图的基本概念_无向图_有向图_子图_生成树_生成森林_完全图
本文介绍了图的基本概念,包括图的定义、无向图与有向图、简单图与多重图等,并解释了顶点度、路径、连通性等相关术语。此外还讨论了子图、生成树、带权图及几种特殊形态的图,如完全图和树等。通过这些概念,读者可以更好地理解图论的基础知识。
|
10天前
|
存储 算法 C语言
数据结构基础详解(C语言): 二叉树的遍历_线索二叉树_树的存储结构_树与森林详解
本文从二叉树遍历入手,详细介绍了先序、中序和后序遍历方法,并探讨了如何构建二叉树及线索二叉树的概念。接着,文章讲解了树和森林的存储结构,特别是如何将树与森林转换为二叉树形式,以便利用二叉树的遍历方法。最后,讨论了树和森林的遍历算法,包括先根、后根和层次遍历。通过这些内容,读者可以全面了解二叉树及其相关概念。
|
10天前
|
存储 C语言
数据结构基础详解(C语言): 树与二叉树的应用_哈夫曼树与哈夫曼曼编码_并查集_二叉排序树_平衡二叉树
本文详细介绍了树与二叉树的应用,涵盖哈夫曼树与哈夫曼编码、并查集以及二叉排序树等内容。首先讲解了哈夫曼树的构造方法及其在数据压缩中的应用;接着介绍了并查集的基本概念、存储结构及优化方法;随后探讨了二叉排序树的定义、查找、插入和删除操作;最后阐述了平衡二叉树的概念及其在保证树平衡状态下的插入和删除操作。通过本文,读者可以全面了解树与二叉树在实际问题中的应用技巧和优化策略。
|
10天前
|
存储 算法 C语言
C语言手撕数据结构代码_顺序表_静态存储_动态存储
本文介绍了基于静态和动态存储的顺序表操作实现,涵盖创建、删除、插入、合并、求交集与差集、逆置及循环移动等常见操作。通过详细的C语言代码示例,展示了如何高效地处理顺序表数据结构的各种问题。
|
存储 程序员 C语言
程序员之路:C语言中存储类别
程序员之路:C语言中存储类别
129 0
|
7天前
|
存储 Serverless C语言
【C语言基础考研向】11 gets函数与puts函数及str系列字符串操作函数
本文介绍了C语言中的`gets`和`puts`函数,`gets`用于从标准输入读取字符串直至换行符,并自动添加字符串结束标志`\0`。`puts`则用于向标准输出打印字符串并自动换行。此外,文章还详细讲解了`str`系列字符串操作函数,包括统计字符串长度的`strlen`、复制字符串的`strcpy`、比较字符串的`strcmp`以及拼接字符串的`strcat`。通过示例代码展示了这些函数的具体应用及注意事项。
|
10天前
|
存储 C语言
C语言程序设计核心详解 第十章:位运算和c语言文件操作详解_文件操作函数
本文详细介绍了C语言中的位运算和文件操作。位运算包括按位与、或、异或、取反、左移和右移等六种运算符及其复合赋值运算符,每种运算符的功能和应用场景都有具体说明。文件操作部分则涵盖了文件的概念、分类、文件类型指针、文件的打开与关闭、读写操作及当前读写位置的调整等内容,提供了丰富的示例帮助理解。通过对本文的学习,读者可以全面掌握C语言中的位运算和文件处理技术。
|
10天前
|
存储 C语言
C语言程序设计核心详解 第七章 函数和预编译命令
本章介绍C语言中的函数定义与使用,以及预编译命令。主要内容包括函数的定义格式、调用方式和示例分析。C程序结构分为`main()`单框架或多子函数框架。函数不能嵌套定义但可互相调用。变量具有类型、作用范围和存储类别三种属性,其中作用范围分为局部和全局。预编译命令包括文件包含和宏定义,宏定义分为无参和带参两种形式。此外,还介绍了变量的存储类别及其特点。通过实例详细解析了函数调用过程及宏定义的应用。
|
16天前
|
Linux C语言
C语言 多进程编程(三)信号处理方式和自定义处理函数
本文详细介绍了Linux系统中进程间通信的关键机制——信号。首先解释了信号作为一种异步通知机制的特点及其主要来源,接着列举了常见的信号类型及其定义。文章进一步探讨了信号的处理流程和Linux中处理信号的方式,包括忽略信号、捕捉信号以及执行默认操作。此外,通过具体示例演示了如何创建子进程并通过信号进行控制。最后,讲解了如何通过`signal`函数自定义信号处理函数,并提供了完整的示例代码,展示了父子进程之间通过信号进行通信的过程。