当前位置: 首页 > news >正文

数据结构---二叉树(概念、特点、分类、特性、读取顺序、例题)、gdb调试指令、时间复杂度(概念、大O符号法、分类)

一、二叉树

1、树

   1)概念        

        树是 n(n >= 0) 个结点的有限集合。若 n=0 ,为空树。

        在任意一个非空树中:

          (1)有且仅有一个特定的根结点;

          (2)当 n>1 时,其余结点可分为 m 个互不相交的有限集合T1、T2......Tm,其中每一个集合又是一个树,并且称为子树。

   2)度、度数、深度

        结点拥有子树的个数称为结点的。度为 0 的结点称为叶结点;度不为 0 称为分支结点。

        树的度数:指在这颗树中,最大的结点的度数,称为树的度数。

        树的深度(高度):指从根开始,根为第一层,根的孩子为第二层,即树的层数,称为树的深度。

        树的存储:顺序结构、链表结构。

2、二叉树(binary tree)

  1)概念

        二叉树是 n 个结点的有限集合,集合要么为空树,要么由一个根节点和两棵互不相交的树组成,这两棵树分别称为根节点的左子树和右子树。

  2)特点

     (1)每个结点最多两个子树。

     (2)左子树和右子树是有顺序的,次序不能颠倒。

     (3)如果某个结点只有一个子树,也要区分左、右子树。

  3)特殊的二叉树

     (1)斜树

        斜树分为两种,一种是所有的结点都只有左子树,称为左斜树;另一种是所有的结点都只有右子树,称为右斜树。

        (2)满二叉树

        满二叉树是指所有的分支结点都存在左右子树,并且叶子都在同一层上。

        (3)完全二叉树

        完全二叉树是指:对于一颗具有 n 个结点的二叉树按照层序编号,如果编号 i( 1<= i <= n )的结点于同样深度的满二叉树中编号为 i 的结点在二叉树中的位置完全相同,则此树称为完全二叉树。

    4)特性

       (1)在二叉树的第 i 层上最多有 2^(i-1) 个结点,i >= 1。

       (2)深度为 k 的二叉树至多有 2^k-1 个结点,k >= 1。

       (3)任意一个二叉树T,如果其叶子结点的个数为 N,度数为 M,则 N=M+1。

       (4)有 n 个结点的完全二叉树深度为(logn / log2)+ 1。

   5)层序

        前序:根左右。先访问根结点,再访问左结点,最后访问右结点。

        中序:左根右。先从根结点开始(不是先访问根结点),从左结点开始访问,再访问根结点,最后访问右结点。

        后序:左右根。先从根结点开始(不是先访问根结点),从左结点开始访问,再访问右结点,最后访问根结点。

     6)二叉树的函数应用

        (1)创建二叉树函数

void CreateTree(BiTNode **root)
{char c = data[ind++];if('#' == c){*root = NULL;return ;}else{*root = malloc(sizeof(BiTNode));if(NULL == *root){printf("malloc error\n");*root = NULL;return ;}(*root) -> data = c;CreateTree(&(*root) -> ichild);CreateTree(&(*root) -> rchild);}return ;
}

       ( 2)根左右(前序)函数封装

//根左右
void PreOrderTraverse(BiTNode *root)
{if(NULL == root){return ;}else{printf("%c", root -> data);PreOrderTraverse(root -> ichild);PreOrderTraverse(root -> rchild);}return ;
}

      (  3)左根右(中序)函数封装

//左根右
void InOrderTraverse(BiTNode *root)
{if(NULL == root){return ;}InOrderTraverse(root -> ichild);printf("%c", root -> data);InOrderTraverse(root -> rchild);return ;
}

        (4)左右根(后序)函数封装

//左右根
void PostOrderTraverse(BiTNode *root)
{if(NULL == root){return ;}PostOrderTraverse(root -> ichild);PostOrderTraverse(root -> rchild);printf("%c", root -> data);return ;
}

        (5)二叉树销毁函数封装

//销毁
void DestroyTree(BiTNode *root)
{if(NULL == root){return ;}DestroyTree(root -> ichild);DestroyTree(root -> rchild);free(root);return ;
}

       ( 6)头文件与其余声明

#include <stdio.h>
#include <string.h>
#include <stdlib.h>typedef char DATATYPE;typedef struct BiTNode
{DATATYPE data;struct BiTNode *ichild, *rchild; 
}BiTNode;char data[] = "Abd#g###ce#h##fi###";
int ind = 0;

       ( 7)主函数运行格式

int main(int argc, char **argv)
{BiTNode *root;CreateTree(&root);PreOrderTraverse(root);printf("\n");InOrderTraverse(root);printf("\n");PostOrderTraverse(root);printf("\n");DestroyTree(root);root = NULL;return 0;
}

二、gbd调试指令

        gdb 调试指令用来寻找段错误。

1、一般调试

      1)gcc -g 文件名

      2)gbd ./a.out (a.out 为该函数的可执行文件)

      3)b  函数名   设置断点,运行到这个函数位置,程序自动暂停

              b   数字     运行到 main函数的这一 “数字” 行,程序自动暂停

      4)r  运行

      5)n  执行下一步(行)步过,若是函数,直接调用结束

      6)p  使用p命令,查看变量或指针等数据,p a(变量); p *a(指针)

2、其他相关命令

      1)bt  与 where  显示栈结构,函数的调用关系

      2)s  步入,如果是函数,进入函数

      3)c  跳出循环,在循环后面设置断点,然后按 c 可返回调用处

      4)display  和 p 相似,一直显示变量

      5)q  退出 gbd 操作界面

三、各类排序算法的时间复杂度

1、概念

        时间复杂度是衡量算法执行效率的重要指标,描述了算法的运行时间随输入规模(n)增长而变化的趋势,而非具体的运行时间。

2、推导大O阶方法

        1)用常数 1 取代运行时间中的所有加法常数。

        2)在修改后的运行次数函数中,只保留最高阶项。

        3)如果最高阶项存在且不是 1 ,则去除与这个项相乘的常数。

得到的结构就是大O阶。

3、表示方法

        采用大O符号(Big O Notation)来表示,忽略了常数项、低阶项和系数,只保留对增长趋势影响最大的项。例如下图:(图中 阶 代表时间复杂度)

4、常见时间复杂度(按效率高到低排序)

   1)常数阶 O(1)

        算法执行时间不随规模 n 变化,始终为固定步骤,如访问数组中的某个元素。

   2)对数阶 O(log n)

        执行时间随 n 增长,但增长速度极慢(每步可将问题规模缩小一半),如二分查找。

   3)线形阶 O(n)

        执行时间与 n 成正比例增长,如线性查找。

   4)线形对数阶 O(n log n)

        效率介于 O(n) 和 O(n^2) 之间,常见于高效排序算法,如快速排序、归并排序。

   5)平方阶 O(n^2)

        执行时间与 n 的平方成正比,适用于小规模数据,如冒泡排序。

   6)指数阶 O(2^n)、阶乘阶 O(n!)4

        效率极低,随 n 增长,执行时间呈爆炸式增长,仅适用于极小规模数据。

5、各类算法时间复杂度整理

常用的时间复杂度所耗费的时间从小到大依次是:

【END】

http://www.dtcms.com/a/322187.html

相关文章:

  • Qwen Agent 入门介绍与简单使用示例
  • 基于STM32单片机的OneNet物联网环境检测系统
  • Vue 路由跳转
  • Vue3生命周期
  • ZK首次连接失败,第二次连接成功的问题解决方案
  • AI入门学习--如何对RAG测试
  • Flutter开发 Switch、SwitchListTile的基本使用
  • 嵌入式LINUX—————系统编程
  • Javascript中的一些常见设计模式
  • 小程序中使用echarts(2025/8/8)
  • 最近看到的提示词相关内容汇总
  • Document Picture-in-Picture API拥抱全新浮窗体验[参考:window.open]
  • K-Means 聚类
  • 液体泄漏识别误报率↓76%:陌讯多模态融合算法实战解析
  • 94、【OS】【Nuttx】【构建】cmake 配置介绍
  • 【Linux】Linux增删改查命令大全(附频率评级)
  • 批量将NC格式数据转换为TIF格式:解决转换后图像颠倒、镜像、翻转等问题
  • 深度剖析主流AI大模型的编程语言与架构选择:行业实践与技术细节解读
  • Uipath Studio中爬取网页信息
  • 安装CST时,报错问题处理
  • 几个概率分布在机器学习应用示例
  • Java-反射
  • C++编程之旅-- -- --类与对象的奇幻征途之初识篇(一)(了解类的基本用法,计算类大小,分析this指针)
  • 【完整源码+数据集+部署教程】海洋物体实例分割系统源码和数据集:改进yolo11-EfficientHead
  • Java【问题 07】SSH不同版本使用jsch问题处理(7.4升级9.7及欧拉原生8.8)
  • WD5202 非隔离降压转换芯片,220V降5V,输出电流80MA
  • Java学习Collection单列集合中的三种通用遍历方法
  • 【Erdas实验教程】029:遥感图像光谱增强(缨帽变换)
  • 经济学从业者职业发展认证体系分析
  • 在 Git 中,将本地分支的修改提交到主分支