初级数据结构——树

目录

前言

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

一、树的基本概念

定义:树是一种非线性的数据结构,由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)。

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

三、树的表示方法

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

四、树的遍历

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

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

树的代码模版

cpp 复制代码
#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. 判断根结点是否等于子结点之和

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

代码题解

cpp 复制代码
/**
 * 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+树等,以满足不同的应用需求。

结语

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

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

相关推荐
QING6182 小时前
Kotlin Delegates.notNull用法及代码示例
android·kotlin·源码阅读
风象南2 小时前
SpringBoot中6种自定义starter开发方法
java·spring boot·后端
QING6182 小时前
Kotlin filterNot用法及代码示例
android·kotlin·源码阅读
mghio10 小时前
Dubbo 中的集群容错
java·微服务·dubbo
咖啡教室15 小时前
java日常开发笔记和开发问题记录
java
咖啡教室15 小时前
java练习项目记录笔记
java
鱼樱前端16 小时前
maven的基础安装和使用--mac/window版本
java·后端
RainbowSea17 小时前
6. RabbitMQ 死信队列的详细操作编写
java·消息队列·rabbitmq
RainbowSea17 小时前
5. RabbitMQ 消息队列中 Exchanges(交换机) 的详细说明
java·消息队列·rabbitmq