先放这张图:

可以看出,树是非线性结构;

一、树的概念

树(tree)是n(n>=0)个节点的有限集合T,它满足两个条件:

1)有且仅有一个特定的称为根(root)的节点;

2)其余的节点可以分为m(m>=0)个互不相交的有限结合T1、T2、...、Tm,其中每一个集合又是一棵树,并成为其根的子数(Subtree)。

树的逻辑结构:树中任何节点都可以有零个或多个直接后继节点(子节点),但至多只有一个直接前驱节点(父节点),根节点没有前驱节点,叶节点没有后继节点。

 度数:一个节点的子树的个数称为该节点的度数,一棵树的度数是指该树中节点的最大度数;

 层数:节点的层数等于父节点的层数加一,根节点的层数定义为一;

 深度:树中节点层数的最大值称为该树的高度或深度;

二、二叉树

       二叉树(Binary)是n(n>=0)个节点的有限集合,它或者是空集(n=0),或者是由一个根节点以及两棵互不相交的、分别称为左子树和右子树的二叉树;二叉树是有序树

二叉树的性质:

满二叉树:深度为k(k>=1)时2ek-1个节点的二叉树;

完全二叉树:1)只有最下面两层有度数小于2的节点;2)最下面一层的叶节点集中在最左边的若干位置上;

满二叉树是完全二叉树的一个特例。

1、二叉树的顺序存储结构

完全二叉树节点的编号方法是从上到下,从左到右,根节点为1号节点。设完全二叉树的节点数为n,某节点编号为i :

1)当i > 1(不是根节点)时,有父节点,其父节点编号为i / 2;

2)当2 * i <= n 时,有左子树,其编号为2 * i,否则没有左子树,本身是叶节点;

3)当2 * i  + 1 < = n时,有右子树,其编号为2 * i + 1,否则没有右子树;

如何存储:

有n个节点的完全二叉树可以用有 n + 1 个元素的数组进行存储,节点号和数组下标一一对应,下标为零的元素不用。

利用以上特性,可以用下标获得节点的逻辑关系。不完全二叉树通过添加虚节点构成完全二叉树,然后用数组存储,这要浪费一些存储空间。

通过添加非字母字符,构成完全二叉树。

2、二叉树的链式存储

1)链式存储结构:

[cpp] view plaincopy
  1. typedef int data_t;
  2. typedef struct node_t //定义二叉树节点的内部结构
  3. {
  4. data_t data;
  5. struct node_t *lchild,*rchild; //指向左孩子和右孩子的指针;
  6. }bitree_t;
  7. bitree_t *root; //定义指向二叉树的指针

2)链式二叉树的创建

链式二叉树的创建要借助顺序存储,比如下面这个二叉树

我们需要通过添加虚节点使其成为一个完全二叉树,并用大小为n+1的数组来表示,如下

data_t a[] = {0,'a','b','c','d','e',0,'f',0,0,'g','h',0,0,'i'}; 因为节点号与数组下表是一一对应的,所以我们可以通过这个数组创建一个链式二叉树

 利用递归创建一个二叉树:

[cpp] view plaincopy
  1. data_t a[] = {0,'a','b','c','d','e',0,'f',0,0,'g','h',0,0,'i'};
  2. bitree_t *CreateBitree(int i, data_t a[], int n)
  3. {
  4. bitree_t *root;
  5. int j;
  6. root = (bitree_t *)malloc(sizeof(bitree_t));
  7. root->data = a[i];
  8. j = 2 * i;
  9. if(j <= n && a[j] != '0')
  10. {
  11. root->lchild = CreateBitree(j, a, n); //创建
  12. }
  13. else
  14. {
  15. root->lchild = NULL;
  16. }
  17. j = 2 * i + 1;
  18. if(j <= n && a[j] != '0')
  19. {
  20. root->rchild = CreateBitree(j, a, n);
  21. }
  22. else
  23. {
  24. root->rchild = NULL;
  25. }
  26. return root;
  27. }

它的遍历顺序:

递归不论是在我们创建二叉树还是遍历二叉树都起到了很大的作用,至于递归,大家可以通过函数栈来理解,函数在执行到 root->lchild = CreateBitree(j, a, n); 这一步时,会再次调用CreateBitree()函数,这样会在栈区开辟一块空间,知道遇到终止条件才会返回,即这片内存区域会被释放,函数执行向上回收,直至该二叉树被创建,大家可以画图理解一下,有空我会补上图;

3、二叉树的遍历

遍历:沿某条搜索路径周游二叉树,对树中的每一个节点访问一次且仅访问一次。

由于二叉树的递归性质,遍历算法也是递归的。三种基本的遍历算法如下:

1)先序遍历:先访问树根,再访问左子树,最后访问右子树;

2)中序遍历:先访问左子树,再访问树根,最后访问右子树;

3)后序遍历:先访问左子树,再访问右子树,最后访问树根;

先序遍历算法:

[cpp] view plaincopy
  1. void PREORDER(bitree_t *r)
  2. {
  3. if(r == NULL)
  4. return;
  5. printf("%c ",r->data);
  6. PREORDER(r->lchild);
  7. PREORDER(r->rchild);
  8. }

中序遍历算法:

[cpp] view plaincopy
  1. void INORDER(bitree_t *r)
  2. {
  3. if(r == NULL)
  4. return;
  5. INORDER(r->lchild);
  6. printf("%c ",r->data);
  7. INORDER(r->rchild);
  8. }

后序遍历算法:

[cpp] view plaincopy
  1. void POSTORDER(bitree_t *r)
  2. {
  3. if(r == NULL)
  4. return;
  5. POSTORDER(r->lchild);
  6. POSTORDER(r->rchild);
  7. printf("%c ",r->data);
  8. }

我们可以把程序整合一下,写个测试程序:

[cpp] view plaincopy
  1. int main()
  2. {
  3. bitree_t *tree;
  4. printf("Begin creating the tree!\n");
  5. tree = CreateBitree(1,a,sizeof(a)/sizeof(data_t) - 1);
  6. printf("Finish!\n");
  7. printf("Preorder traversal:\n");
  8. PREORDER(tree);
  9. printf("\nInorder traversal:\n");
  10. INORDER(tree);
  11. printf("\nPostorder traversal:\n");
  12. POSTORDER(tree);
  13. printf("\n");
  14. return 0;
  15. }

执行结果如下:

[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/tree/bitree$ ./bitree
  2. Begin creating the tree!
  3. Finish!
  4. Preorder traversal:
  5. a b d e g h c f i
  6. Inorder traversal:
  7. d b g e h a c i f
  8. Postorder traversal:
  9. d g h e b i f c a
  10. fs@ubuntu:~/qiang/tree/bitree$

Linux C 数据结构——二叉树相关推荐

  1. go移植linux内核书名叫啥,Go语言移植Linux内核数据结构hlist

    hlist(哈希链表)可以通过相应的Hash算法,迅速找到相关的链表Head及节点. 在有些应用场景,比Go标准库提供的list(一种双向链表)更合适. 依照list.h中的源码,我实现了一个Go语言 ...

  2. 数据结构 -- 二叉树

          这篇文章介绍的是经典的数据结构--二叉树,在这篇文章里介绍了几乎二叉树的所有操作.       二叉树给我们最重要的印象莫过于递归,因为这棵树就是递归的,所以,我在解决各个问题时大部分都用 ...

  3. 数据结构 - 二叉树 - 面试中常见的二叉树算法题

    数据结构 - 二叉树 - 面试中常见的二叉树算法题 数据结构是面试中必定考查的知识点,面试者需要掌握几种经典的数据结构:线性表(数组.链表).栈与队列.树(二叉树.二叉查找树.平衡二叉树.红黑树).图 ...

  4. 数据结构——二叉树的递归算法

    二叉树的结构定义: typedef struct BiNode {TElemType data;struct BiNode *lchild;struct BiNode *rchild; }BiNode ...

  5. 数据结构——二叉树的层次遍历进阶

    之前的一个博客 数据结构--二叉树的层次遍历看完这个,可以简单实现下面的问题 问题: 1.计算二叉树的最大宽度(二叉树的最大宽度是指二叉树所有层中结点个数的最大值. 2.用按层次顺序遍历二叉树的方法, ...

  6. 数据结构----二叉树叶子结点到根节点的高度计算

    数据结构----二叉树叶子结点到根节点的高度计算 代码: #include<stdio.h> #include<stdlib.h> typedef struct bstTree ...

  7. 数据结构 二叉树的存储结构_线程二叉树| 数据结构

    数据结构 二叉树的存储结构 线程二叉树 (Threaded Binary Tree ) A binary tree can be represented by using array represen ...

  8. 二叉树----数据结构:二叉树的三种遍历及习题

    二叉树----数据结构:二叉树的三种遍历,利用递归算法. 关于二叉树的遍历,应用非常广泛,不单单是访问打印结点,还可以进行一系列的操作,如赋值.删除.查找.求二叉树的深度等等. 有递归和非递归两种算法 ...

  9. 数据结构-二叉树入门Go语言实现

    数据结构-二叉树入门Go语言实现 之前我们一直在谈的是一对一的线性结构,可现实中,还有很多一对多的情况需要处理,所以我们需要研究这种一对多的数据结构--"树",考虑它的各种特性,来 ...

最新文章

  1. [深入浅出Cocoa]iOS网络编程之Socket
  2. 如何查看开发者账号何时到期
  3. Echart---多项柱状图-2D/H5
  4. 应用性能问题解决实际案例
  5. 前端学习(3249):react的文件src
  6. WEB安全基础-文件操作漏洞
  7. linux内核Kconfig语法
  8. 【模块化开发】之 Webpack、Rollup、Parcel
  9. jython语法入门
  10. Docker笔记2 容器及其基本操作
  11. python 封装对象数据_Python数据库封装实现代码示例解析
  12. Spring→面向切面编程AOP、相关概念、通知Advice类型、配置切面切入点通知、AOP相关API、AOP代理类ProxyFactoryBean、AOP注解@AspectJ
  13. 列表页 编辑页 删除页
  14. 完全开源:带OLED超级Mini的SWD离线烧写器!
  15. ui设计为什么要切图,切图是什么意思?
  16. 7-22 循环日程表
  17. Handheld Multi-Frame Super-Resolution论文理解
  18. android 文件预览(读取)
  19. 工信部发布《移动互联网应用程序个人信息保护管理暂行规定(征求意见稿)》
  20. 几个主流的Java连接池

热门文章

  1. VSS2005 上传pdf 空白
  2. 关系型数据库的核心单元是_核中的数据关系
  3. 551. 学生出勤记录
  4. ⚡如何在2分钟内将GraphQL服务器添加到RESTful Express.js API
  5. 如何使用动态工具提示构建React Native图表
  6. gt爵士变形步骤_代码广播简介:您可以编码为24/7的爵士节拍
  7. 帮助中心 开源_对开源的贡献帮助我获得了Microsoft的实习机会。 这就是它可以为您提供帮助的方式。
  8. 为什么印度盛产码农_印度农产品价格的时间序列分析
  9. Koa 中实现 chunked 数据传输
  10. LeetCode || Copy List with Random Pointer