定义

线性表是一对一,但是树就不一样了,一对多的性质扑面而来,先看一下百度的说法吧,
树:它是由n(n≥1)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

树中的专有名词

就用这张图来描述树的特征:

  • 当n=0,就称为空树
  • 有且只有一个称为根的结点,这里为A
  • 当n>1时,其余结点可以分为m(m>0)个互不相交的有限集,其中每个集合又是一棵树,称为子树
  • 举个例子:
    是以B为结点的子树

下面我们来将结点分一下类:

  1. 树的结点包含一个数据结构及若干指向其子树的分支
  2. 结点拥有的子树称为结点的度
  3. 度为0的结点称为叶结点或终端结点
  4. 度不为0的结点称为非终端结点或分支结点
    看图

    结点的关系:
    这块有点像我们的家庭关系,比较好理解
    像上图A为B,C的双亲,B,C互为兄弟,对于#来说,D,B,A,都是它的祖先,反之A的子孙有B,D,#

其他相关概念,特定情况才会用到

引入了深度,可以说是有几层就有多少深度.
无序树:如果将树中结点的各子树看成从左到右都是没有次序,都可以随意互换,则称为无序树,反之为有序树

树中的基本操作

双亲表示法

树真的太像人了,人可能暂时没有孩子但是一定有且只有一个父母,树也一样除了根结点外,其余每个结点,它不一定有孩子,但是一定有且只有一个双亲

/*
Project: Tree_parent(树-双亲表示法)基本操作函数:
InitTree(Tree &T) 参数T,树根节点 作用:初始化树,先序递归创建
InsertNode(Tree &T, TElemType node) 插入树的结点 参数:树T,结点node 作用:在双亲数组中插入结点,增加树的结点值
InsertParent(Tree &T, TElemType node1, TElemType node2)//插入双亲数组的双亲域 参数:树T ,结点node1,结点node2//作用:使双亲数组中,node2对应的双亲域为node1的下标
GetIndegree(Tree &T, TElemType node)                   //得到某结点入度 参数:树T,结点node 结点不存在返回-1
GetOutdegree(Tree &T, TElemType node)                  //得到某结点出度 参数:树T,结点node 结点不存在返回-1
PreOrder(Tree T)  参数:树T,根节点下标 作用:先序遍历树
PostOrder(Tree T) 参数:树T,根节点下标 作用:后序遍历树
LevelOrder(Tree T)参数:树T            作用:层序遍历树
功能实现函数:
CreateTree(Tree &T) 参数T,树根节点 作用:创建树,调用InsertNode,InsertParent
Traverse(Tree T)    参数T,树根节点 作用:PreOrder InOrder PostOrder LevelOrder遍历树
*/
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<string>
#include<stack>
#include<queue>
#include<algorithm>
#include<iostream>
#define TElemType char
#define Max 100
using namespace std;
//树的结点数据结构
typedef struct TNode
{TElemType data;//数据域int parent;    //双亲
}TNode;
//树的数据结构
typedef struct Tree
{TNode parent[Max];int NodeNum;}Tree;
//********************************基本操作函数********************************//
//初始化树函数 参数:树T 作用:规定数据域为#,则为空,双亲为-1,则为空
void InitTree(Tree &T)
{for (int i=0;i<Max;i++){T.parent[i].data = '#';T.parent[i].parent = -1;}T.NodeNum = 0;
}
//插入树的结点 参数:树T,结点node 作用:在双亲数组中插入结点,增加树的结点值
bool InsertNode(Tree &T, TElemType node)
{if (node != '#'){T.parent[T.NodeNum++].data = node;//插入到双亲数组中return true;}return false;
}
//插入双亲数组的双亲域 参数:树T ,结点node1,结点node2
//作用:使双亲数组中,node2对应的双亲域为node1的下标
bool InsertParent(Tree &T, TElemType node1, TElemType node2)
{int place1, place2;place1 = -1;place2 = -1;for (int i=0;i<T.NodeNum;i++)//查找两点是否存在{if (node1 == T.parent[i].data)place1 = i;if (node2 == T.parent[i].data)place2 = i;}if (place1 != -1 && place2 != -1)//两点均存在{T.parent[place2].parent = place1;return true;}return false;
}
//得到某结点入度 参数:树T,结点node 结点不存在返回-1
int GetIndegree(Tree &T, TElemType node)
{int place = -1;for (int i = 0;i<T.NodeNum;i++){if (T.parent[i].data == node)place = i;}if (place!=-1)//结点存在{if(T.parent[place].parent!=-1)return 1;//双亲只能有一个else return 0; //根节点没有双亲,即没有入度}return -1;
}
//得到某结点出度 参数:树T,结点node 结点不存在返回-1
int GetOutdegree(Tree &T, TElemType node)
{int place = -1;int outdegree = 0;for (int i = 0;i<T.NodeNum;i++){if (T.parent[i].data == node)place = i;}if (place != -1){for (int i = 0;i < T.NodeNum;i++){if (T.parent[i].parent == place)outdegree++;}return outdegree;}return -1;
}
//先序遍历 参数:树T,根节点下标
void PreOrder(Tree T,int i)
{if (T.NodeNum != 0){cout << T.parent[i].data << " ";for(int j=0;j<T.NodeNum;j++){if(T.parent[j].parent==i)PreOrder(T,j);//按左右先序遍历子树}}
}
//后序遍历 参数:树T,根节点下标
void PostOrder(Tree T,int i)
{if (T.NodeNum != 0){for (int j = 0;j<T.NodeNum;j++){if (T.parent[j].parent == i)PostOrder(T, j);//按左右先序遍历子树}cout << T.parent[i].data << " ";}
}
//层序遍历 参数:树T
void LevelOrder(Tree T)
{queue<TNode> q;//借助队列if (T.NodeNum!=0){TNode temp;//暂存要出队的结点q.push(T.parent[0]);//根结点入队while (!q.empty())//队列非空{temp = q.front();q.pop();cout<<temp.data<<" ";for (int j = 0;j<T.NodeNum;j++){if (T.parent[T.parent[j].parent].data == temp.data)//当前结点的父节点的数据域与弹出的相同 //因为temp没有保存下标,只能按这种方式比较,默认结点名称不同q.push(T.parent[j]);//队列先进先出,先入左孩子}}}
}
//**********************************功能实现函数*****************************//
//创建树,调用InsertNode,InsertParent
void CreateTree(Tree &T)
{int nodenum = 0;int parent;TElemType node,node1,node2;printf("请输入树的结点个数:");cin >> nodenum;parent = nodenum - 1;printf("请输入树的结点名称(空格隔开):");while (nodenum--){cin >> node;InsertNode(T,node);}printf("请输入树的结点间的双亲关系(一对为一双亲关系,A B表示A为B的双亲):\n");while (parent--){cin >> node1>>node2;InsertParent(T,node1,node2);}printf("\n");
}
//入度
void Indegree(Tree &T)
{TElemType node;int indegree;printf("请输入结点名称:\n");cin >> node;indegree = GetIndegree(T, node);if (-1 != indegree)cout << "该结点入度为:" << indegree << endl;elsecout << "结点不存在。" << endl;
}
//出度
void Outdegree(Tree &T)
{TElemType node;int outdegree;printf("请输入结点名称:\n");cin >> node;outdegree = GetOutdegree(T, node);if (-1 != outdegree)cout << "该结点出度为:" << outdegree << endl;elsecout << "结点不存在。" << endl;
}
//遍历功能函数 调用PreOrder InOrder PostOrder LevelOrder
void Traverse(Tree T)
{int choice;while (1){printf("********1.先序遍历    2.后序遍历*********\n");printf("********3.层次遍历    4.返回上一单元*********\n");printf("请输入菜单序号:\n");scanf("%d", &choice);if (4 == choice) break;switch (choice){case 1: {printf("树先序遍历序列:");PreOrder(T,0);printf("\n");}break;case 2: {printf("树后序遍历序列:");PostOrder(T,0);printf("\n");}break;case 3: {printf("树层序遍历序列:");LevelOrder(T);printf("\n");}break;default:printf("输入错误!!!\n");break;}}
}
//菜单
void menu()
{printf("********1.创建     2.某点入度*********\n");printf("********3.某点出度 4.遍历*************\n");printf("********5.退出\n");
}
//主函数
int main()
{Tree T;int choice = 0;InitTree(T);while (1){menu();printf("请输入菜单序号:\n");scanf("%d", &choice);if (5 == choice) break;switch (choice){case 1:CreateTree(T);break;case 2:Indegree(T);break;case 3:Outdegree(T);break;case 4:Traverse(T);break;default:printf("输入错误!!!\n");break;}}return 0;
}

所用图

孩子表示法

顾名思义,就是每个结点有多个指针域,其中每个指针指向一棵子树的根结点,我们也把这种方法叫做多重链表表式法,有点像线性表中的链式表示法
那么这样的话,我这里就写伪代码了

//指针域的个数就等于树的度,其中树的度又等于树各个结点度的最大值
struct ChildNode
{int data;ChildNode*;
}
ChildNode *D;//d为最大结点
d.ChildNode;

不难看出这样的话,如果各个树度之间的差距不大,还可以,但是如果各个树度之间的差距很大,那么很浪费空间,原因是许多的结点域都是空的

孩子兄弟表示法

这个可以说是学二叉树的基础,有的兄弟可能要说了,为什么不是兄弟表示法?还要带上我的孩子一起?
因为可能存在下面这种情况,只有了兄弟,孩子没有办法往下延申了,那么如何孩子和兄弟一起开呢?
是这样的,任意一棵树,它的结点的第一个孩子如果存在就是唯一的,它的右兄弟如果存在也是唯一的,记得不是堂兄弟昂,是亲兄弟,下面我们看图


观察后,我们可以发现每个结点最多有俩个孩子,也就是一个简单的二叉树,这也可以说是,孩子兄弟表示法最大的好处

struct Node
{int data;*firstchild,*ringtsib;
}
Node *Tree;

刷题巩固

相同的树

数据结构——树(树的基本概念)相关推荐

  1. 【数据结构】 树与二叉树的基本概念、结构特点及性质

    前言:本章内容主要是数据结构中树与二叉树的基本概念.结构特点及性质的引入. 文章目录 树的概念 树的特点: 树的常用术语: 树的表示: 代码创建: 树在实际中的应用: 二叉树的概念 特殊的二叉树 满二 ...

  2. 【数据结构基础/接口函数编写】二叉树第一弹之树和堆的概念和结构、基础堆接口函数的实现(编写思路加逻辑分析加代码实操,一应俱全的汇总)

    文章目录 树的概念及结构 树的概念 树的相关概念 树的表示 二叉树的概念及结构 二叉树的概念 特殊的二叉树: 二叉树的存储结构 二叉树的性质 顺序储存 链式储存 堆 堆的概念及结构 堆的实现 头文件 ...

  3. 考研复习之数据结构笔记(九)树(上)(树和二叉树的概念、特征、性质及相关实例)

    目录 一.树的基本概念和术语 1.1 基本定义与特点 (1)基本定义: (2)基本特点 1.2 树的基本术语 1.3 树的基本性质 二.二叉树 2.1 二叉树的定义与性质 (1)基本概念 (2)与树的 ...

  4. 数据结构之树的概念以及结构

    数据结构之树的概念以及结构 1.树的概念 树是一种非线性的数据结构,是由n(n>=0)有限节点的组成的一个具有线性关系的集合. 叫树的原因是因为它看起来像是一颗倒挂的树,只不过是根朝上,叶朝下 ...

  5. 数据结构——树及二叉树的概念及结构的了解

    文章目录 一.树概念及结构? 1.树的概念 2.树的相关概念 3.树的表示 4. 树在实际中的运用 二.叉树的概念及结构 1.概念 2.现实中的二叉树 3.特殊的二叉树 4.二叉树的性质 5.二叉树的 ...

  6. 数据结构显示树的所有结点_您需要了解的有关树数据结构的所有信息

    数据结构显示树的所有结点 When you first learn to code, it's common to learn arrays as the "main data struct ...

  7. 数据结构-王道-树和二叉树

    [top] 树和二叉树 树:是\(N(N\geq0)\)个结点的有限集合,\(N=0\)时,称为空树,这是一种特殊情况.在任意一棵非空树中应满足: 有且仅有一个特定的称为根的结点. 当\(N>1 ...

  8. 树 - 定义和基本概念

    一.树(Tree)是n(n>=0)个结点的有限集.n=0时称为空树.在任意一棵非空树中:(1)有且仅有一个特定的称为根(root)的结点. (2)当n>1时,其余结点可分为m(m>0 ...

  9. 树结构之树和二叉树的概念以及如何用面向对象思想进行结构定义01

    树和二叉树的概念及结构定义 前言 一.树的基本概念及代码层面如何定义 1.树的概念 2.代码层面树如何定义 二.二叉树的基本概念及代码层面如何定义 1.二叉树的概念 2.代码层面二叉树如何定义 3.二 ...

  10. 重温数据结构:树 及 Java 实现(转)

    转自:http://blog.csdn.net/u011240877/article/details/53193877 读完本文你将了解到: 什么是树 树的相关术语 根节点父亲节点孩子节点叶子节点如上 ...

最新文章

  1. 去除Coding4Fun中MessagePrompt的边框(Border)
  2. GraphQL 初探—面向未来 API 及其生态圈
  3. sharepoint 2010 如何使用sharepoint多媒体视频播放media webpart功能
  4. linux i2c 读写函数,Linux下读写芯片的I2C寄存器
  5. ubuntu11.04 安装sun-java6-jdk_Ubuntu下安装sun-java6-jdk和eclipse
  6. [016]转--C++拷贝构造函数详解
  7. 阿里云弹性高性能计算E-HPC强势来袭,全新打造一站式云超算
  8. Redis:15---键迁移(move、dump、restore、migrate)
  9. 查看文件md5_软件推荐丨go-fastdfs——高性能、高可靠分布式文件系统
  10. 初探mysql innodb集群_MySQL InnoDB Cluster搭建
  11. [导入]+ADO.NET读书笔记系列 一+
  12. oracle添加字段sql并添加注释
  13. 科研作图软件介绍附带AI安装包
  14. 输入一行字符,分别统计出其中英文字母、空格、数字和其他字符的个数。
  15. mediawiki 各种扩展整理
  16. python金融大数据分析师工资待遇_请问数据分析师这个工作怎么样,是否值得成为努力方向?...
  17. google sdk speech-to-text(谷歌语音转文本、谷歌语音转字幕)
  18. 英语语法(1)——简单句
  19. Verilog语言快速入门(一)
  20. win10离线安装framework3.5以及dism找不到源文件解决方法(已测试有效)

热门文章

  1. 国内IT服务管理软件ITSM的七个发展趋势
  2. locust工具学习笔记(三)-Tasks属性、tag修饰符、TaskSet类
  3. maven打包报错 Failed to execute goal org.apache.maven.plugins:maven-jar-plugin:3.0.2:jar
  4. android开发非-转动圆形菜单
  5. 有15个数按从小到大的顺序存放在一个数组中。(折半查找)
  6. 连接 mysql 数据库的 失败_MySQL_连接MySQL数据库失败频繁的原因分析,连接mySQL数据库失败频繁,主 - phpStudy...
  7. 地图采集车的那些事 | 惯性导航
  8. Ubuntu系列(一):给英特尔NUC重装 ubuntu18.04 的系统
  9. php-java-net-python-爱心公益网站()计算机毕业设计程序
  10. 前端知识合集【重中之重】,我只看这一篇!