赞
踩
数据结构 —— 顺序表
数据结构 —— 单链表
数据结构 —— 双向链表
数据结构 —— 队列
数据结构 —— 栈
数据结构 —— 堆
数据结构 —— 二叉树
数据结构 —— 八大排序
数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。数据结构是一种十分优秀的解决实际问题的模板,是先进思想的结晶。博主将会用代码结合大量图解,对数据结构进行深度剖析,以便大家更好的学习数据结构的思想。
通过层级目录可以找到它的子文件
树的引入:树是一种重要的非线性数据结构,直观地看,它是数据元素(在树中称为结点)按分支关系组织起来的结构
树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。
节点的度: 一个节点含有的子树的个数称为该节点的度; 如上图:A的为6
叶节点或终端节点: 度为0的节点称为叶节点; 如上图:B、C、H、I…等节点为叶节点
非终端节点或分支节点: 度不为0的节点; 如上图:D、E、F、G…等节点为分支节点
双亲节点或父节点: 若一个节点含有子节点,则这个节点称为其子节点的父节点; 如上图:A是B的父节点
孩子节点或子节点: 一个节点含有的子树的根节点称为该节点的子节点; 如上图:B是A的孩子节点
兄弟节点: 具有相同父节点的节点互称为兄弟节点; 如上图:B、C是兄弟节点
树的度: 一棵树中,最大的节点的度称为树的度; 如上图:树的度为6
节点的层次: 从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
树的高度或深度: 树中节点的最大层次; 如上图:树的高度为4
堂兄弟节点: 双亲在同一层的节点互为堂兄弟;如上图:H、I互为兄弟节点
节点的祖先: 从根到该节点所经分支上的所有节点;如上图:A是所有节点的祖先
子孙: 以某节点为根的子树中任一节点都称为该节点的子孙。如上图:所有节点都是A的子孙
森林: 由m(m>0)棵互不相交的树的集合称为森林;
树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,既然保存值域,也要保存结点和结点之间的关系。
树的表示法:
我们这里就简单的了解其中最常用的孩子兄弟表示法。
typedef int DataType;
struct Node {
DataType _data; // 结点中的数据域
struct Node* _firstChild1; // 第一个孩子结点
struct Node* _pNextBrother; // 指向其下一个兄弟结点
};
二叉树是结点的一个有限集合
由上图可知:
注意:对于任意的二叉树都是由以下几种情况复合而成的
二叉树的结构类型:左右子树的链式存储结构
二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。
typedef int BTDataType;
typedef struct BinaryTreeNode {
BTDataType data;
struct BinaryTreeNode *left; // 左子树
struct BinaryTreeNode *right; // 右子树
}BTNode;
满二叉树: 一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是 说,如果一个二叉树的层数为K,且结点总数是 ,则它就是满二叉树。
完全二叉树: 完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K 的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对 应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。
创建一个二叉树的根节点
// 创建二叉树
BTNode *CreateTree() {
BTNode *newSpace = (BTNode *)malloc(sizeof(BTNode));
assert(newSpace);
return newSpace;
}
三种非常重要的遍历思想
前序遍历(根 - 左 - 右)
// 二叉树前序遍历
void PreOrder(BTNode* root) {
if (root == NULL) {
printf("NULL ");
return;
}
printf("%d ", root->data);
PreOrder(root->left);
PreOrder(root->right);
}
中序遍历(左 - 根 - 右)
// 二叉树中序遍历
void InOrder(BTNode* root) {
if (root == NULL) {
printf("NULL ");
return;
}
InOrder(root->left);
printf("%d ", root->data);
InOrder(root->right);
}
后序遍历(左 - 右 - 根)
// 二叉树后序遍历
void PostOrder(BTNode* root) {
if (root == NULL) {
printf("NULL ");
return;
}
PostOrder(root->left);
PostOrder(root->right);
printf("%d ", root->data);
}
后序遍历的思想:先遍历到最深处进行判断
// 二叉树节点的个数(子问题思路解决)
int TreeSize(BTNode* root) {
return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
后序遍历思想:递归到最深处进行判断
// 二叉树叶子节点的个数
int TreeLeafSize(BTNode* root) {
if (root == NULL) {
return 0;
} else if (root->left == NULL && root->right == NULL) {
return 1;
} else {
return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}
}
分割分治子问题思想:将左右子树看作新的二叉树继续递归
// 二叉树的高度
int TreeHeight(BTNode *root) {
if (root == NULL) {
return 0;
} else {
int left = TreeHeight(root->left);
int right = TreeHeight(root->right);
return left > right ? left + 1 : right + 1;
}
}
后序遍历思想:递归到最深处进行判断
// 二叉树第k层节点个数
int TreeKLevel(BTNode *root, int k) {
assert(k > 0);
if (root == NULL) {
return 0;
} else if (k == 1) {
return 1;
} else {
return TreeKLevel(root->left, k - 1) + TreeKLevel(root->right, k - 1);
}
}
前序遍历思想:递归到最深处进行判断
// 二叉树查找值为x的节点 BTNode* BinaryTreeFind(BTNode* root, BTDataType x) { if (root == NULL) { return NULL; } else if (root->data == x) { return root; } // 先找左 BTNode * leftNode = BinaryTreeFind(root->left, x); if (leftNode) { return leftNode; } // 再找右 BTNode * rightNode = BinaryTreeFind(root->right, x); if (rightNode) { return rightNode; } return NULL; }
释放堆申请的空间
// 二叉树的销毁
void BinaryTreeDestroy(BTNode* root) {
if (root == NULL) {
return;
}
BinaryTreeDestroy(root->left);
BinaryTreeDestroy(root->right);
free(root);
}
二叉树是解决实际问题时极其常用的一种数据结构,是非常重要的解决问题的方式。二叉树的各种接口的复现,有利于更好的学习数据结构的思想,有利于开阔视野,学习前辈的智慧结晶。对我们后续解决实际问题也会有很大帮助。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。