数据结构-----树

news/2025/3/26 4:04:26/

一、树的基本概念

1. 树的结构定义
  • 递归定义
    • 空树(n=0)
    • 非空树(n≥1):
      • 唯一根结点
      • m个互不相交的子树(m≥0)
2. 核心术语
术语说明图示示例
结点的度结点的子树个数
树的度树中所有结点的最大度数二叉树度为2
叶结点度为0的结点树结构末端结点
分支结点度≠0的结点包含子树的结点
树的深度根到叶结点的最大层数(根为1)3层树深度为3

二、二叉树核心特性

1. 二叉树定义
  • 每个结点最多两个子树
  • 子树有明确左右之分(不可互换)
2. 特殊二叉树类型
类型特征示例
斜树所有结点只有左/右子树
满二叉树所有分支结点都有左右子树,叶子在同一层
完全二叉树层序编号与满二叉树对应,最后一层结点左对齐
3. 重要性质
  1. 层节点数:第i层最多2<sup>i-1</sup>个结点(i≥1)
  2. 总节点数:深度k的树最多2<sup>k</sup>-1个结点
  3. 叶节点关系:n<sub>0</sub> = n<sub>2</sub> +1(n<sub>0</sub>:叶结点,n<sub>2</sub>:度为2结点)
  4. 完全二叉树深度:⌊log<sub>2</sub>n⌋+1

三、二叉树存储结构

1. 顺序存储
#define MAX_SIZE 100
typedef struct {int data[MAX_SIZE];  // 按层序存储int size;
} SeqBinaryTree;// 完全二叉树示例
int parent(int i) { return i/2; }
int left(int i) { return 2*i; }
int right(int i) { return 2*i+1; }
2. 链式存储
typedef struct BiTNode {int data;struct BiTNode *lchild, *rchild;
} BiTNode;BiTNode* CreateNode(int val) {BiTNode *new = (BiTNode*)malloc(sizeof(BiTNode));new->data = val;new->lchild = new->rchild = NULL;return new;
}

四、遍历算法实现

五、二叉树结构定义

typedef char DATATYPE;typedef struct BiTNode {DATATYPE data;                   // 结点数据struct BiTNode *lchild;          // 左孩子指针struct BiTNode *rchild;          // 右孩子指针
} BiTNode;

六、核心操作实现

1. 二叉树创建(先序输入)

char dat[] = "ABD##E##CF##G##";  // 示例输入(#表示空结点)
int inx = 0;void CreateTree(BiTNode **root) {char c = dat[inx++];if ('#' == c) {*root = NULL;return;}*root = (BiTNode*)malloc(sizeof(BiTNode));if (NULL == *root) {perror("malloc failed");exit(EXIT_FAILURE);}(*root)->data = c;CreateTree(&((*root)->lchild));  // 递归创建左子树CreateTree(&((*root)->rchild));  // 递归创建右子树
}

输入示例

A         --> 根
├─B       --> 左子树
│ ├─D     --> B的左子树
│ └─E     --> B的右子树
└─C       --> 右子树├─F     --> C的左子树└─G     --> C的右子树

七、遍历算法实现

1. 递归遍历

// 先序遍历
void PreOrderTraverse(BiTNode *root) {if (root) {printf("%c ", root->data);    // 访问根PreOrderTraverse(root->lchild);PreOrderTraverse(root->rchild);}
}// 中序遍历
void InOrderTraverse(BiTNode *root) {if (root) {InOrderTraverse(root->lchild);printf("%c ", root->data);    // 访问根InOrderTraverse(root->rchild);}
}// 后序遍历
void PostOrderTraverse(BiTNode *root) {if (root) {PostOrderTraverse(root->lchild);PostOrderTraverse(root->rchild);printf("%c ", root->data);    // 访问根}
}

遍历结果

先序:A B D E C F G 
中序:D B E A F C G 
后序:D E B F G C A 

 八、内存管理

1. 二叉树销毁(后序释放)

void DestroyBiTree(BiTNode *root) {if (root) {DestroyBiTree(root->lchild);  // 递归释放左子树DestroyBiTree(root->rchild);  // 递归释放右子树free(root);  // 释放当前结点root = NULL;  // 避免野指针}
}

内存释放顺序

D → E → B → F → G → C → A

九、应用扩展接口

1. 计算二叉树深度
int TreeDepth(BiTNode *root) {if (!root) return 0;int left = TreeDepth(root->lchild);int right = TreeDepth(root->rchild);return (left > right ? left : right) + 1;
}
2. 统计结点数量
int CountNodes(BiTNode *root) {if (!root) return 0;return 1 + CountNodes(root->lchild) + CountNodes(root->rchild);
}
2. 二叉搜索树
// 查找操作(递归)
BiTNode* BSTSearch(BiTNode *root, int key) {if(!root || root->data == key) return root;if(key < root->data)return BSTSearch(root->lchild, key);elsereturn BSTSearch(root->rchild, key);
}

十、复杂度对比

操作平均复杂度最坏情况
遍历O(n)O(n)
查找(BST)O(log n)O(n)(退化成链)
插入/删除O(log n)O(n)

http://www.ppmy.cn/news/1583130.html

相关文章

LeetCode 热题 100----2.移动零

LeetCode 热题 100----2.移动零 题目描述 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。示例 1:输入: nums [0,1,0,3,12] 输出: [1,3,12,…

requestAnimationFrame和requestIdleCallback分别是什么,是用在什么场景下

深入解析 requestAnimationFrame 和 requestIdleCallback requestAnimationFrame (rAF) 和 requestIdleCallback (rIC) 都是浏览器提供的 异步调度 API&#xff0c;但它们的执行时机和用途完全不同。 API主要用途何时执行是否保证执行适合场景requestAnimationFrame高优先级 U…

如何使用go的template模版

tmpl, err tmpl.New("page_content").Parse(fmt.Sprintf({{template "%s" .}}, contentBlockName)) 创建新块&#xff1a; tmpl.New("page_content")&#xff1a;在模板对象tmpl中定义一个新的、名为"page_content"的块。这个块是动…

深入剖析Java虚拟机(JVM):从零开始掌握Java核心引擎

&#x1f4cc; 引言&#xff1a;为什么每个Java开发者都要懂JVM&#xff1f; 想象你是一名赛车手&#xff0c;Java是你的赛车&#xff0c;而JVM就是赛车的引擎。 虽然你可以不关心引擎内部构造就能开车&#xff0c;但要想在比赛中获胜&#xff0c;必须了解引擎如何工作&#…

3:库的增删查改,编码,备份恢复

1. 数据库增删查改&#xff1a; show databases; //展示数据库 create database xxx; //创建数据库xxx&#xff0c;本质在var/lib/mysql下创建一个xxx目录 drop database xxx; // 删除数据库xxx&#xff0c;本质在var/lib/mysql下删除xxx目录 create database xxx charsetutf8…

线程池实现学习笔记1

线程池实现学习笔记 今天花了一些时间学习和实现了线程池&#xff0c;收获颇丰。在这里记录一下自己的学习心得&#xff0c;希望对大家也有帮助。 为什么需要线程池&#xff1f; 在实际开发中&#xff0c;如果每个任务都创建一个新线程&#xff0c;当任务数量很大时会带来以…

SQL Optimization

SQL Optimization &#xff08;SQL 优化&#xff09; 1) * && field SELECT * from sys_user SELECT USER_ID, USER_NAME, EMAIL FROM SYS_USER; 栗子&#xff1a; 48.664s 142877rows 6.194s 142877rows 2&#xff09;UNION && UNION ALL …

单链表的查找和插入,删除操作

1.单链表的查找 snode* slistfind(snode* stlheap, stltype x) {while (stlheap){if (stlheap->data x){return stlheap;}stlheap stlheap->next;}return NULL; } 2.单链表的插入操作 2.1在指定位置之前插入节点 void slistinsert(snode** stlheap, snode* pos, stl…