当前位置: 首页 > article >正文

初级数据结构——树

目录

  • 前言
  • 一、树的基本概念
  • 二、二叉树
  • 三、树的表示方法
  • 四、树的遍历
  • 树的代码模版
  • 五、经典例题
    • [2236. 判断根结点是否等于子结点之和](https://leetcode.cn/problems/root-equals-sum-of-children/description/)
      • 代码题解
  • 六、总结
  • 结语

前言

从这一期开始数据结构开始有那么一点复杂了,这期我们一起来学习初级数据结构——树,树是数据结构中的一个重要概念,它用于表示具有层次关系的数据集合。
在这里插入图片描述

一、树的基本概念

定义:树是一种非线性的数据结构,由n(n>=0)个有限节点组成一个具有层次关系的集合。它看起来像一棵倒挂的树,根朝上,叶朝下。

特殊节点:
根节点:树中唯一的特殊节点,没有前驱节点。
子节点:根节点外的其余节点,被分成M(M>0)个互不相交的集合,每个集合又是一棵子树。
叶子节点:度为0的节点,即没有子节点的节点。
分支节点:度不为0的节点,即含有子节点的节点。
节点关系
双亲节点(父节点):若一个节点含有子节点,则这个节点称为其子节点的父节点。
孩子节点(子节点):一个节点含有的子树的根节点称为该节点的子节点。
兄弟节点:具有相同父节点的节点互称为兄弟节点。
堂兄弟节点:双亲在同一层的节点互为堂兄弟。
祖先节点:从根到该节点所经分支上的所有节点。
子孙节点:以某节点为根的子树中任一节点都称为该节点的子孙。
树的度:树中节点的最大度,即节点的最大子树数。
树的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推。
树的高度(深度):树中节点的最大层次。

二、二叉树

定义:二叉树是节点的一个有限集合,该集合为空或由一个根节点加上两棵别称为左子树和右子树的二叉树组成。二叉树的子树有左右之分,次序不能颠倒。

特殊二叉树
满二叉树:每一层上的节点数都是最大节点数,即每一层i的节点数都是2^i。
完全二叉树:叶子节点只能在层次最大的两层上出现,且对任一节点,若其右分支的子孙的最大层次为l,则其左分支的子孙的最大层次必是l或l+1。完全二叉树可以由满二叉树引伸出来,是效率很高的数据结构。

二叉树的性质:
在二叉树的第i层上至多有2^(i-1)个节点(i>=1)。
深度为k的二叉树至多有2^k-1个节点(k>=1)。
对于任何一颗二叉树,其叶子节点数为n0,度为2的节点数为n2,则n0=n2+1。
具有n个节点的完全二叉树的深度为log2n+1(向下取整,n>0)。

二叉树的存储结构:
顺序存储结构:使用数组来存储,一般适合表示完全二叉树。对于非完全二叉树,可能会造成空间浪费。
链式存储结构:用链表来表示二叉树,链表中的每个节点由数据域和左右指针域组成,左右指针分别用来给出该节点左孩子和右孩子所在的链节点的存储地址。链式结构又分为二叉链和三叉链。

三、树的表示方法

树有多种表示方法,包括树形表示法、孩子兄弟表示法、文氏图表示法、凹形表示法、括号表示法等。其中,树形表示法是最常用的方法,每个节点指向若干孩子节点,以此类推。

四、树的遍历

树的遍历是指按照某种规则访问树中的每个节点,使得每个节点被访问且仅被访问一次。常见的遍历方法包括先根遍历、后根遍历和中序遍历(针对二叉树)。

先根遍历:先遍历根节点再遍历它的子节点。
后根遍历:先遍历子节点再遍历根节点。
中序遍历(针对二叉树):先访问左子树,再访问根,再访问右子树。

树的代码模版

#include<iostream>
using namespace std;

template<typename T>
struct ListNode {
	T data;
	ListNode* next;
	ListNode(T x):data(x),next(NULL){}
};

template<typename T>
struct TreeNode {
	T data;
	ListNode<TreeNode<T>*>* childrenHead;//子节点指针
	TreeNode() {
		childrenHead = NULL;
	}
	void Addchild(TreeNode<T>* node) {//增加子节点的接口
		ListNode<TreeNode<T>*>* childNode = new ListNode<TreeNode<T>*>(node);
		if (childrenHead == NULL) childrenHead = childNode;
		else {
			childNode->next = childrenHead;
			childrenHead = childNode;
		}
	}
};

template<typename T>
class Tree {
private:
	TreeNode<T>* root;
	TreeNode<T>* nodes;
public:
	Tree();
	Tree(int maxNode);
	~Tree();
	TreeNode<T>* getTreeNode(int id);
	void setRoot(int rootId);
	void AddChild(int sonId, int parentId);
	void AssignData(int nodeId, T data);
	void Print(TreeNode<T>* node = NULL);
};

template<typename T>
Tree<T>::Tree() {
	nodes = new TreeNode<T>[100001];
}

template<typename T>
Tree<T>::Tree(int maxNodes) {
	nodes = new TreeNode<T>[maxNodes];
}

template<typename T>
Tree<T>::~Tree() {
	delete[]nodes;
}

template<typename T>
TreeNode<T>* Tree<T>::getTreeNode(int id) {
	return &nodes[id];
}

template<typename T>
void Tree<T>::setRoot(int rootId) {
	root = getTreeNode(rootId);
}

template<typename T>
void Tree<T>::AddChild(int parentId, int sonId) {
	TreeNode<T>* parentNode = getTreeNode(parentId);
	TreeNode<T>* sonNode = getTreeNode(sonId);
	parentNode->Addchild(sonNode);
}

template<typename T>
void Tree<T>::AssignData(int nodeId, T data) {
	getTreeNode(nodeId)->data = data;
}

template<typename T>
void Tree<T>::Print(TreeNode<T>* node) {
	if (node == NULL)node = root;
	cout << node->data;
	ListNode<TreeNode<T>*>* temp = node->childrenHead;
	while (temp) {
		Print(temp->data);
		temp = temp->next;
	}
}
int main() {
	Tree<char>t(9);
	t.setRoot(0);
	t.AssignData(0, 'a');
	t.AssignData(1, 'b');
	t.AssignData(2, 'c');
	t.AssignData(3, 'd');
	t.AssignData(4, 'e');
	t.AssignData(5, 'f');
	t.AssignData(6, 'g');
	t.AssignData(7, 'h');
	t.AssignData(8, 'i');

	t.AddChild(0, 2);
	t.AddChild(0, 1);
	t.AddChild(1, 3);
	t.AddChild(2, 5);
	t.AddChild(2, 4);
	t.AddChild(3, 8);
	t.AddChild(3, 7);
	t.AddChild(3, 6);

	t.Print();
	return 0;
}

五、经典例题

2236. 判断根结点是否等于子结点之和

(蓝色字体可以点进去看原题)

代码题解

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool checkTree(TreeNode* root) {
        return root->val==root->left->val+root->right->val;
    }
};

六、总结

综上所述,树是一种重要的数据结构,它用于表示具有层次关系的数据集合。在树的基础上,还可以构建出更复杂的树形结构,如二叉树、B树、B+树等,以满足不同的应用需求。

结语

下期我们将一起学习初级数据结构——二叉树,我们这期不见不散

在这里插入图片描述

想看更多内容可以关注我,看我作品,关注我让我们一起学习编程,希望大家能点赞关注支持一下,让我有持续更新的动力,谢谢大家

在这里插入图片描述


http://www.kler.cn/a/406452.html

相关文章:

  • 计算机网络socket编程(4)_TCP socket API 详解
  • 【LeetCode热题100】栈
  • 全面击破工程级复杂缓存难题
  • 神经网络10-Temporal Fusion Transformer (TFT)
  • 从 IDC 到云原生:稳定性提升 100%,成本下降 50%,热联集团的数字化转型与未来展望
  • Spark SQL大数据分析快速上手-完全分布模式安装
  • Element-UI中el-input输入手机号时,如何限制只能输入数字
  • django基于Django的二手电子设备交易平台设计与开发
  • 服务机器人三甲坎德拉:用智能化开启售后服务新篇章
  • 使用OpenAI进行自动化报告和数据解读
  • 【spark】远程debug spark任务(含有pyspark)
  • 接口测试和单元测试
  • ChatClient:探索与AI模型通信的Fluent API
  • VITE 忽略指定路径的资源
  • 医学图像语义分割:前列腺肿瘤、颅脑肿瘤、腹部多脏器 MRI、肝脏 CT、3D肝脏、心室
  • 一线大厂面试集锦
  • 【Linux】环境搭建Qwen2-VL-7B模型(图文详解-成果案例)
  • linux搭建Gray
  • 【初阶数据结构篇】单链表OJ题(上篇)
  • linux下使用vscode编译及引用动态链接库
  • 基于迅为RK3568开发板全国产平台,快速实现APP开机自启动技术分享
  • 什么是ARM
  • Django如何配置多个环境的MySQL数据库
  • (微信小程序)基于Spring Boot的校园失物招领平台的设计与实现(vue3+uniapp+mysql)
  • MongoDB 更新集合名
  • 【鸿蒙】实现新闻上下轮播滚动效果-harmonyos