手撕数据结构与算法——树(三指针描述一棵树)

简介: 手撕数据结构与算法——树(📖作者介绍:22级树莓人(计算机专业),热爱编程<目前在c++阶段,因为最近参加新星计划算法赛道(白佬),所以加快了脚步,果然急迫感会增加动力>——目标Windows,MySQL,Qt,数据结构与算法,Linux,多线程,会持续分享学习成果和小项目的📖作者主页:king&南星📖专栏链接:数据结构🎉欢迎各位→点赞👏 + 收藏💞 + 留言🔔​💬总结:希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🐾————————————————版权声明:本文为CSDN博主「热爱编程的小K」的原创文章,遵循CC 4.0 BY-S三指针描述一棵树)

9b9b67a20c5d4fddb2f4a78eda506af8.png

🏅文章目录

🌱树

一、🌲概念与定义

二、🌳定义与预备

三、🌴创建结点函数

四、🍀查找

五、🍁插入

六、🍃遍历

🌱树

一、🌲概念与定义

描述树结构:

和现实世界的树 反着画

根节点 枝干 叶子节点

同一层 兄弟 上层:父 叔叔 上层的上层:爷爷

下层:孩子 侄儿

树的高度:几代人

树退化成线性结构 : 一叉树(链表) N代单传

数据结构中的树是和现实倒着的

948f755b2fd24fd3994fa49db8a961aa.png

cf184e26f22745bc9bf90ab48ce529f4.png

详细解读:三个指针描述,一个指针指向父亲,一个指针指向兄弟,一个指针指向孩子,同时规则设定只有父亲的第一个孩子才可以有孩子

二、🌳定义与预备

先准备好头文件、结构体和函数声明

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

#include<stdlib.h>

#include<stdbool.h>

#include<assert.h>

typedef struct treeNode

{

int data;                  //数据

struct treeNode* pParent;  //指向父

struct treeNode* pBrother; //指向第一个兄弟

struct treeNode* pChild;   //指向第一个孩子

}treeNode;

#define SIZE sizeof(treeNode)

//创建节点函数

treeNode* createNode(int data);

//在树中找一个节点,找到返回这个节点的地址,找不到返回NULL

treeNode* findNode( treeNode* root, int findData);

//插入一个节点到树中

//把insertData插入到*pRoot树中 如果isChild为真成为findData节点的孩子,否则成为findData节点的兄弟

bool intsertNode( treeNode** pRoot, int findData, int insertData, bool isChild);

//遍历

void print_Tree(treeNode* root);

三、🌴创建结点函数

这里利用一个技巧,直接使用内存设置函数memset函数,把三个指针内存都设置为0

treeNode* createNode( int data )

{

treeNode* newNode = (treeNode*)malloc(SIZE);

assert(newNode);

memset(newNode, 0, SIZE);  //内存都设置为0

newNode->data = data;

return newNode;

}

四、🍀查找

在树中找一个节点,找到返回这个节点的地址,找不到返回NULL

先在while循环中遍历同一层的兄弟,直到他下一个兄弟为空,切换到下一层,如此循环下去,如果找到则返回地址,如果没找到则返回空

treeNode* findNode(treeNode* root, int findData)  

{

if (NULL == root) return NULL;  //防呆

treeNode* pTemp;

treeNode* pnextChild = root;

while (true)

{

 pTemp = pnextChild;

 if (NULL == pnextChild) break;

 while( true )

 {

  //遍历兄弟层

  if (NULL == pTemp) break;

  if (findData == pTemp->data) return pTemp;

  pTemp = pTemp->pBrother;

 }

 //切换到下一层(孩子)

 pnextChild = pnextChild->pChild;

}

return NULL;

}

五、🍁插入

描述:插入一个节点到树中,把insertData插入到*pRoot树中 如果isChild为真成为findData节点的孩子,否则成为findData节点的兄弟

99513581e3b440b6a188d5fe8dc0f923.png

bool intsertNode(treeNode** pRoot, int findData, int insertData, bool isChild)

{

if (NULL == pRoot) return false; //防呆

if (NULL == *pRoot) //空树

{

 *pRoot = createNode(insertData);

 return true;

}

treeNode* pFind = findNode(*pRoot, findData);  //查找

if (NULL == pFind) return false;

treeNode* pNew, * pTemp;

//找到了

if (isChild) //新节点成为pFind指向节点的孩子

{

 //有孩子,新节点成为pFind节点孩子的最小兄弟

 if (pFind->pChild)

 {

  pTemp = pFind->pChild;

  pNew = createNode(insertData);

  while (pTemp->pBrother) pTemp = pTemp->pBrother;

  pTemp->pBrother = pNew;

  pNew->pParent = pFind;

  return true;

 }

 //pFind指向的节点没有孩子

 else

 {

  //有父,pFind不是根节点

  if (pFind->pParent)

  {

   //pFind是pFind->pPartent的第一个孩子

   if (pFind->pParent->pChild == pFind)

   {

    pNew = createNode(insertData);

    pFind->pChild = pNew;

    pNew->pParent = pFind;

    return true;

   }

   else

   {

    //pFind不是pFind->pParent的第一个孩子

    //新节点只能成为 pFind->pParent->pChild的孩子

    intsertNode(&(pFind->pParent), pFind->pParent->pChild->data, insertData, true);

   }

  }

  //无父,pFind是根节点

  else

  {

   pNew = createNode(insertData);

   pFind->pChild = pNew;

   pNew->pParent = pFind;

   return true;

  }

 }

}

else //新节点成为pFind指向节点的兄弟

{

 pTemp = pFind;

 while (pTemp->pBrother) pTemp = pTemp->pBrother;

 pNew = createNode(insertData);

 pTemp->pBrother = pNew;

 pNew->pParent = pFind->pParent;

 return true;

}

return false;

}

六、🍃遍历

和查找函数异曲同工

void print_Tree(treeNode* root)  

{

if (NULL == root) return NULL;  //防呆

treeNode* pTemp;

treeNode* pnextChild = root;

int cnt = 1;

while (true)

{

 pTemp = pnextChild;

 if (NULL == pnextChild) break;

 printf("第[%d]层:", cnt++);

 while (true)

 {

  //遍历兄弟层

  if (NULL == pTemp) break;

  printf("%d ", pTemp->data);

  pTemp = pTemp->pBrother;

 }

 printf("\n");

 //切换到下一层(孩子)

 pnextChild = pnextChild->pChild;

}

}

版权声明:本文为CSDN博主「热爱程的小K」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/qq_72157449/article/details/129628960

相关文章
|
1月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
46 10
|
1月前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
60 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
1月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
48 12
|
1月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
51 2
|
2月前
|
算法 容器
【算法】——双指针算法合集(力扣)
移动零,复写零,快乐数,盛最多水的容器,有效三角形的个数,和为s的两个数(查找总价格为目标值的两个商品 ),三数之和,四数之和
|
3月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
99 5
|
3月前
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
81 4
|
3月前
|
算法
数据结构之文件系统模拟(树数据结构)
本文介绍了文件系统模拟及其核心概念,包括树状数据结构、节点结构、文件系统类和相关操作。通过构建虚拟环境,模拟文件的创建、删除、移动、搜索等操作,展示了文件系统的基本功能和性能。代码示例演示了这些操作的具体实现,包括文件和目录的创建、移动和删除。文章还讨论了该算法的优势和局限性,如灵活性高但节点移除效率低等问题。
91 0
|
3月前
|
算法
数据结构之博弈树搜索(深度优先搜索)
本文介绍了使用深度优先搜索(DFS)算法在二叉树中执行遍历及构建链表的过程。首先定义了二叉树节点`TreeNode`和链表节点`ListNode`的结构体。通过递归函数`dfs`实现了二叉树的深度优先遍历,按预序(根、左、右)输出节点值。接着,通过`buildLinkedList`函数根据DFS遍历的顺序构建了一个单链表,展示了如何将树结构转换为线性结构。最后,讨论了此算法的优点,如实现简单和内存效率高,同时也指出了潜在的内存管理问题,并分析了算法的时间复杂度。
78 0
|
3月前
|
算法
树的遍历算法有哪些?
不同的遍历算法适用于不同的应用场景。深度优先搜索常用于搜索、路径查找等问题;广度优先搜索则在图的最短路径、层次相关的问题中较为常用;而二叉搜索树的遍历在数据排序、查找等方面有重要应用。
61 2

热门文章

最新文章