书接上文,这篇博客接着来讲一下关于二叉树和堆的一点小知识
二叉树顺序结构的实现
在这一块内容中,二叉树顺序结构的实现主要只通过数组实现的,但是普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。
给一些图示说明:
在上面这个图片能够很好的说明在二叉树的顺序存储是如何实现的。在我的上篇博文中主要提到了顺序结构的应用堆的很多应用,堆的创建,堆的删除,堆的插入,堆的排序等。
二叉树链式结构
在二叉树的链式结构中主要是遍历这一块应用的比较多。设计不同的节点结构可以构成不同形式的链式存储结构。有二叉树的定义得知,二叉树的结点由一个数据元素和分别指向其左,右子树的两个分支组成,则表示二叉树的链表中的结点至少包含3个域:数据域和左右指针域。给图说明一下:
而刚才说明所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问 题。 遍历是二叉树上最重要的运算之一,是二叉树上进行其它运算之基础。前序/中序/后序的递归结构遍历:是根据访问结点操作发生位置命名
- NLR:前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前。
- LNR:中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。
- LRN:后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。
由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtree)和R(Right subtree)又可解释为
根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。
层序遍历:除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。
接下来给一下遍历的代码:
前序遍历:
int BSize(struct TreeNode* root) {
if(root == NULL)
return 0;
return BSize(root->left)
+ BSize(root->right) + 1; }
void _preOrder(struct TreeNode* root, int* a, int* pi) {
if(root)
{
//前序遍历,保存当前节点的值
a[*pi] = root->val;
++(*pi);
_preOrder(root->left, a, pi);
_preOrder(root->right, a, pi);
}
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
int* a, i;
*returnSize = BSize(root);
a = (int*) malloc(sizeof(int) * (*returnSize));
i = 0;
_preOrder(root, a, &i);
return a;
}
中序遍历:
int BSize(struct TreeNode* root) {
if(root == NULL)
return 0;
return BSize(root->left)
+ BSize(root->right) + 1; }
void _InOrder(struct TreeNode* root, int* a, int* pi)
{
if(root)
{
_InOrder(root->left, a, pi);
a[*pi] = root->val;
++(*pi);
_InOrder(root->right, a, pi);
}
}
int* inorderTraversal(struct TreeNode* root, int* returnSize){
int* a, i;
*returnSize = BSize(root);
a = (int*) malloc(sizeof(int) * (*returnSize));
i = 0;
_InOrder(root, a, &i);
return a; }
后序遍历:
int BSize(struct TreeNode* root) {
if(root == NULL)
return 0;
return BSize(root->left)
+ BSize(root->right) + 1; }
void _postorderTraversal(struct TreeNode* root, int* a, int* pi) {
if(root)
{
_postorderTraversal(root->left, a, pi);
_postorderTraversal(root->right, a, pi);
a[*pi] = root->val;
++(*pi);
}
}
int* postorderTraversal(struct TreeNode* root, int* returnSize){
int* a, i;
*returnSize = BSize(root);
a = (int*) malloc(sizeof(int) * (*returnSize));
i = 0;
_postorderTraversal(root, a, &i);
return a; }
以上就是这一篇博客的主要内容了,在数据结构中二叉树是很重要的东西。还有介绍一些关于这个的东西的。