C语言数据结构(12)--链表描述子节点的树

简介: 本文目录1. 数组描述子节点的缺点2. 使用链表描述3. 代码实现4. 执行结果

1. 数组描述子节点的缺点

如果有这么一颗奇葩的树,大多数节点的孩子数为1-2个,但是有一个节点的孩子数是100个。


因为我们使用数组描述子节点,所以描述子节点的数组得定义为struct TreeNode* children[100];。


也就是说,除了有一个充分利用了数组分配的空间,其他的都造成了极大浪费,毫无疑问不合理。


2. 使用链表描述

孩子也是一个一维的集合,特点个数不确定,符合这种特点的数据结构就是链式线性表了(简称链表)。


我们再来仔细观察下树的结构图,来尝试定义节点的数据结构:

image.png

首先一个节点得有一个数据区域,保存节点的数据信息,最简单就是保存一个int数据。

每个节点有多个孩子,这个可以使用一个链表来描述,因为链表指定了头指针,就能把整个链表带出来,所以可以定义节点为。

typedef struct {

int data;//数据区域

TreeNode* node;//保存孩子中的头结点

}TreeNode;


上面的节点数据结构乍一看没啥问题,对于节点1来说,data区域保存1,node的data保存2,node的node指向3。


但是2下面的5和6呢,已经没有地方存储了。


我们再次仔细分析下节点,实际上每个节点除了要通过一个链表保存兄弟节点,还需要一个链表保存孩子节点。


于是结构应该为:


typedef struct {

int data;//数据区域

TreeNode* brother;//保存兄弟节点 如果为NULL表示无

TreeNode* son;//保存孩子节点 如果为NULL表示无

}TreeNode;


也就是说,我们的存储结构实际上是,同样能表达含义一模一样的树。

image.png

3. 代码实现

嗯,这个代码已经有一定理解难度了,我也是写了大概几十分钟才搞定的,C语言真是魅力无穷吭,喷香!

/*
* 使用链表描述子节点的普通树实现
* 作者:熊猫大大
* 时间:2019-10-16
*/
#include <stdio.h>
typedef struct {
  int data;//数据区域
  struct TreeNode* brother;//保存兄弟节点 如果为NULL表示无
  struct TreeNode* son;//保存孩子节点 如果为NULL表示无
}TreeNode;
//为树的当前节点添加子节点
int addChild(TreeNode* curNode, int data)
{
  //分配新节点
  TreeNode* newNode= (TreeNode*)malloc(sizeof(TreeNode));
  newNode->data = data;
  newNode->brother = NULL;
  newNode->son = NULL;
  //找到当前节点的最后一个字节点
  TreeNode* lastSonNode = curNode->son;//指向第一个子节点
  if (lastSonNode == NULL) //第一个子节点即为空
  {
    curNode->son = newNode;
    return 1;
  }
  while (lastSonNode->brother != NULL) //找到最后一个节点
  {
    lastSonNode = lastSonNode->brother;
  }
  lastSonNode->brother = newNode;//将新节点挂在最后一个节点后面
  return 1;
}
//遍历当前节点与子节点
void printTree(TreeNode *node)
{
  printf("父节点:%d",node->data);
  //遍历打印子节点
  printf("----子节点:");
  TreeNode *p = node->son;
  if (p == NULL) //无子节点
  {
    printf("无\n");
    return 1;
  }
  if (p != NULL) 
  {
    printf("%d ",p->data);
  }
  while(p->brother!=NULL)
  {
    p = p->brother;
    printf("%d ", p->data);
  }
  printf("\n");
  //遍历递归子节点
  TreeNode *q = node->son;
  if (q != NULL)
  {
    printTree(q);
  }
  while (q->brother != NULL)
  {
    q = q->brother;
    printTree(q);
  }
}
//----------------------------------------------------------------------------------------------------测试入口区域
int main()
{
  //设定根节点
  TreeNode root;
  root.data = 1;//根节点数据区域
  root.brother = NULL;//根节点无兄弟节点
  root.son = NULL;//一开始也没有子节点
  //为1节点添加2/3/4子节点
  addChild(&root,2);
  addChild(&root, 3);
  addChild(&root, 4);
  //为2号节点添加5/6子节点
  TreeNode *node2 = root.son;
  addChild(node2, 5);
  addChild(node2, 6);
  //为3号节点添加7子节点
  TreeNode *node3 = node2->brother;
  addChild(node3, 7);
  //为4号节点添加8子节点
  TreeNode *node4 = node3->brother;
  addChild(node4, 8);
  printTree(&root);
  return 1;
}

4. 执行结果

毫无疑问,执行结果验证了代码的真实性,但是输出顺序稍微有点乱。

主要是因为现在的输出是顺着一个节点,将其子节点输出完,才输出另外节点的逻辑,如果不好理解下个断点走走就是了。

image.png

相关文章
|
12月前
|
算法 数据处理 C语言
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
463 1
|
8月前
|
算法 Java
算法系列之数据结构-Huffman树
Huffman树(哈夫曼树)又称最优二叉树,是一种带权路径长度最短的二叉树,常用于信息传输、数据压缩等方面。它的构造基于字符出现的频率,通过将频率较低的字符组合在一起,最终形成一棵树。在Huffman树中,每个叶节点代表一个字符,而每个字符的编码则是从根节点到叶节点的路径所对应的二进制序列。
175 3
 算法系列之数据结构-Huffman树
|
8月前
|
存储 自然语言处理 数据库
【数据结构进阶】AVL树深度剖析 + 实现(附源码)
在深入探讨了AVL树的原理和实现后,我们不难发现,这种数据结构不仅优雅地解决了传统二叉搜索树可能面临的性能退化问题,还通过其独特的平衡机制,确保了在任何情况下都能提供稳定且高效的查找、插入和删除操作。
575 19
|
9月前
|
定位技术 C语言
c语言及数据结构实现简单贪吃蛇小游戏
c语言及数据结构实现简单贪吃蛇小游戏
|
10月前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
244 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
10月前
|
搜索推荐 C语言
数据结构(C语言)之对归并排序的介绍与理解
归并排序是一种基于分治策略的排序算法,通过递归将数组不断分割为子数组,直到每个子数组仅剩一个元素,再逐步合并这些有序的子数组以得到最终的有序数组。递归版本中,每次分割区间为[left, mid]和[mid+1, right],确保每两个区间内数据有序后进行合并。非递归版本则通过逐步增加gap值(初始为1),先对单个元素排序,再逐步扩大到更大的区间进行合并,直至整个数组有序。归并排序的时间复杂度为O(n*logn),空间复杂度为O(n),且具有稳定性,适用于普通排序及大文件排序场景。
|
10月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
205 12
|
10月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
176 10
|
10月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
300 3
|
11月前
|
存储 算法 C语言
【C语言】深入浅出:C语言链表的全面解析
链表是一种重要的基础数据结构,适用于频繁的插入和删除操作。通过本篇详细讲解了单链表、双向链表和循环链表的概念和实现,以及各类常用操作的示例代码。掌握链表的使用对于理解更复杂的数据结构和算法具有重要意义。
3203 6

热门文章

最新文章

下一篇
开通oss服务