学习嵌入式第二十二天

文章目录

二叉树

  • 非线性结构

1.概念

  • 线性结构:描述数据一对一的关系(表)
  • 非线性结构:描述数据一对多(树),多对多(图)的关系

2.树形结构

  • 节点:组成树形结构的一个小的单元
    • 根节点:只有后继,没有前驱
    • 分支节点:既有前驱,又有后继
    • 叶子节点:只有前驱,没有后继
  • 前驱(祖先):被访问节点的上一个节点
  • 后继(子孙):节点后续访问的节点
  • 层:根节点层数为1,后续节点,每层层数+1
  • 树的层数:由最高节点对应层数表示
  • 高度:由该节点到最远叶子节点的层数距离(节点高度自身为1)
  • 深度:由该节点到根节点的距离(节点自身深度为1)
  • 树的高度=树的深度=数的层数
  • 度:后续节点个数

3.二叉树

  • 树形结构中的所有节点度数最大为2

  • 节点类型

    • 叶子节点
    • 只有左孩子
    • 只有右孩子
    • 左右孩子都有
  • 满二叉树和完全二叉树

    • 满二叉树

      1. 概念:所有叶子节点均在同一层,且每层节点个数均为最大值
      2. 特性
        • 第k层节点有 2 k 2^k 2k
        • 前k层节点有 2 k − 1 2^k -1 2k−1
    • 完全二叉树

      1. 概念:编号(如果节点编号为n,左孩子编号:2n,右孩子:2n+1)展开是连续的

      2. 遍历形式

        深度优先遍历(DFS)

        • 前序遍历(先序遍历):分节点,左孩子,右孩子
        • 中序遍历:左孩子,分节点,右孩子
        • 后序遍历:左孩子,右孩子,分节点

        广度优先遍历(BFS)

        • 层序遍历:逐层从左到右依次遍历

4.二叉树的操作

1.节点定义

代码实现:

c 复制代码
typedef struct tree{

    int num;
    struct tree *pleftchild;
    struct tree *prightchild;

}treenode;

2.依赖的头文件

1.linkqueue.h(声明在栈和队列中)
C 复制代码
#include"btree.h"

extern linknode *create_empty_linkqueue(void);
extern int is_empty_linkqueue(linknode *phead);
extern int enter_linkqueue(linknode *phead, datatype tmpdata);
extern datatype quit_linkqueue(linknode *phead);
extern int destroy_linkqueue(linknode **pphead);
2.linkstack.h(声明在栈和队列中)
c 复制代码
#include"btree.h"

extern linknode *create_empty_linkstack(void);
extern int is_empty_linkstack(linknode *phead);
extern int push_linkstack(linknode *phead, datatype tmpdata);
extern datatype pop_linkstack(linknode *phead);
extern int destroy_linkstack(linknode **pphead);
3.btree.h
C 复制代码
typedef struct tree{

    int num;    //编号
    struct tree *pleftchild;    //右子树根节点地址
    struct tree *prightchild;   //左子树根节点地址
    char data;  //数据
    int flag;

}treenode;
/* 存放数据的类型 */
typedef treenode *datatype;

/* 链表节点类型 */
typedef struct node 
{
    datatype data;
    struct node *pnext;
}linknode;

extern treenode *create_complete_btree(int startnum, int endnum);
extern int preorder_btree(treenode *proot);
extern int inorder_btree(treenode *proot);
extern int postorder_btree(treenode *proot);
extern int destroy_btree(treenode *proot);
extern int levelorder_btree(treenode *proot);
extern treenode *create_btree(void);
extern int get_btree_height(treenode *proot);
extern int preorder_btree_nonrec(treenode *proot);
extern int inorder_btree_nonrec(treenode *proot);
extern int postorder_btree_nonrec(treenode *proot);

3.创建完全二叉树

  • 通过函数递归完成完全二叉树的创建
    • 申请节点空间
    • 存放数据空间
    • 如果存在左子树递归创建左子树
    • 如果存在右子树递归创建右子树

代码实现:

c 复制代码
treenode *create_complete_btree(int startnum,int endnum){

    treenode *proot = NULL;
    proot = malloc(sizeof(treenode));

    if(NULL == proot){

        perror("fail to malloc");
        return NULL;
    }
    proot->num = startnum;
    proot->pleftchild = NULL;
    proot->prightchild = NULL;
    if(2 * startnum <= endnum){

        proot->pleftchild = create_complete_btree(2 * startnum,endnum);
    }
    if(2 * startnum + 1 <= endnum){

        proot->prightchild = create_complete_btree(2 * startnum + 1,endnum);
    }
    return proot;

}

4.二叉树深度优先遍历(递归实现)

  • 前序遍历

    代码实现:

    c 复制代码
    int preorder_btree(treenode *proot){
    
        printf("%c ",proot->data);
        if(proot->pleftchild != NULL){
    
         preorder_btree(proot->pleftchild);   
        }
        if(proot->prightchild != NULL){
    
            preorder_btree(proot->prightchild);
        }
        return 0;
    }
  • 中序遍历

    代码实现:

    c 复制代码
    int inorder_btree(treenode *proot){
    
        if(proot->pleftchild != NULL){
    
            inorder_btree(proot->pleftchild);
        }
        printf("%c ",proot->data);
        if(proot->prightchild != NULL){
    
         inorder_btree(proot->prightchild);   
        }
        return 0;
    }
  • 后序遍历

    代码实现:

    c 复制代码
    int postorder_btree(treenode *proot){
    
        if(proot->pleftchild != NULL){
    
            postorder_btree(proot->pleftchild);
        }
        if(proot->prightchild != NULL){
    
            postorder_btree(proot->prightchild);
        }
        printf("%c ",proot->data);
        return 0;
    }

5.二叉树的广度优先遍历

  • 层序遍历

    利用队列实现

    1. 根节点入队
    2. 根节点出队,左孩子入队,右孩子入队
    3. 左孩子出队,左孩子的左孩子入队,左孩子的右孩子入队
    4. 右孩子出队,右孩子的左孩子入队,右孩子的右孩子入队
    5. ...

    代码实现:

    c 复制代码
    int levelorder_btree(treenode *proot){
    
        linknode *ptmpnode = NULL;
        ptmpnode = create_empty_linkqueue();
        treenode *tmpdata = NULL;
    
        enter_linkqueue(ptmpnode,proot);
        while(!is_empty_linkqueue(ptmpnode)){
    
            tmpdata = quit_linkqueue(ptmpnode);
            printf("%c ",tmpdata->data);
            if(tmpdata->pleftchild != NULL){
    
                enter_linkqueue(ptmpnode,tmpdata->pleftchild);
            }
            if(tmpdata->prightchild != NULL){
    
                enter_linkqueue(ptmpnode,tmpdata->prightchild);
            }
    
        }
        destroy_linkqueue(&ptmpnode);
        return 0;
    }

6.二叉树的销毁

代码实现:

C 复制代码
int destroy_btree(treenode *proot){

    if(proot->pleftchild != NULL){

        destroy_btree(proot->pleftchild);
    }
    if(proot->prightchild != NULL){

        destroy_btree(proot->prightchild);
    }
    free(proot);
    return 0;
}

7.创建一个非完全二叉树

代码实现:

c 复制代码
treenode *create_btree(void){

    char ch = 0;
    treenode *ptmpnode =NULL;

    scanf(" %c",&ch);
    if(ch == '#'){

        return NULL;
    }
    ptmpnode = malloc(sizeof(treenode));

    if(NULL == ptmpnode){

        perror("fail to malloc");
        return NULL;
    }
    ptmpnode->data = ch;
    ptmpnode->pleftchild = create_btree();
    ptmpnode->prightchild = create_btree();

    return ptmpnode;
}

8.获得树的高度、深度、层数

代码实现:

c 复制代码
int get_btree_height(treenode *proot){

    int leftheight = 0;
    int rightheight = 0;
    if(NULL == proot){

        return 0;
    }
    leftheight = get_btree_height(proot->pleftchild);
    rightheight = get_btree_height(proot->prightchild);

    return (leftheight > rightheight ? leftheight : rightheight) + 1;
}

9.二叉树的深度优先遍历(非递归实现)

  • 从根节点出发到叶子节点,所有左孩子入栈

  • 出栈一个节点元素

  • 将该节点的右孩子按照一二步循环操作,直到栈空为止

    1. 前序遍历

      在入栈前打印节点数据

      代码实现:

      c 复制代码
      int preorder_btree_nonrec(treenode *proot){
      
          linknode *ptmpstack = NULL;
          treenode *ptmpnode = NULL;
      
          ptmpstack = create_empty_linkstack();
      
          ptmpnode = proot;
          while(1){
      
              while(ptmpnode != NULL){
      
                  printf("%c ",ptmpnode->data);
                  push_linkstack(ptmpstack,ptmpnode);
                  ptmpnode = ptmpnode->pleftchild;
              }
              if(is_empty_linkstack(ptmpstack)){
      
                  break;
              }
              ptmpnode = pop_linkstack(ptmpstack);
              ptmpnode = ptmpnode->prightchild;
          } 
          destroy_linkstack(&ptmpstack);
      
          return 0;
      }
    2. 中序遍历

      在出栈时打印节点数据

      代码实现:

      C 复制代码
      int inorder_btree_nonrec(treenode *proot){
      
          linknode *ptmpstack = NULL;
          treenode *ptmpnode = NULL;
      
          ptmpstack = create_empty_linkstack();
      
          ptmpnode = proot;
      
          while(1){
      
              while(ptmpnode != NULL){
      
                  push_linkstack(ptmpstack,ptmpnode);
                  ptmpnode = ptmpnode->pleftchild;
              }
              if(is_empty_linkstack(ptmpstack)){
      
                  break;
              }
              ptmpnode = pop_linkstack(ptmpstack);
              printf("%c ",ptmpnode->data);
              ptmpnode = ptmpnode->prightchild;
          }
          destroy_linkstack(&ptmpstack);
          return 0;
      }
    3. 后序遍历

      • 因为最后打印根节点,所以节点都需要两次入栈
      • 第一次入栈,为了出栈时找到该节点的右孩子,找到后,将该节点和右孩子一起入栈
      • 第二次入栈,打印该节点

      代码实现:

      c 复制代码
      int postorder_btree_nonrec(treenode *proot){
      
          linknode *ptmpstack = NULL;
          treenode *ptmpnode = NULL;
      
          ptmpstack = create_empty_linkstack();
      
          ptmpnode = proot;
      
          while(1){
      
              while(ptmpnode != NULL){
      
                  ptmpnode->flag = 1;
                  push_linkstack(ptmpstack,ptmpnode);
                  ptmpnode = ptmpnode->pleftchild;
              }
              if(is_empty_linkstack(ptmpstack)){
      
                  break;
              }
              ptmpnode = pop_linkstack(ptmpstack);
              if(1 == ptmpnode->flag){
      
                  ptmpnode->flag = 0;
                  push_linkstack(ptmpstack,ptmpnode);
                  ptmpnode = ptmpnode->prightchild;
              }
              else if(0 == ptmpnode->flag){
      
                  printf("%c ",ptmpnode->data);
                  ptmpnode = NULL; // 置空,防止重复输出
              }
          }
          destroy_linkstack(&ptmpstack);
      
          return 0;
      }
相关推荐
Asu52021 小时前
思途spring学习0807
java·开发语言·spring boot·学习
Vesan,2 小时前
无人机开发分享——基于行为树的无人机集群机载自主决策算法框架搭建及开发
c++·算法·决策树·无人机
爱coding的橙子3 小时前
每日算法刷题Day58:8.7:leetcode 单调栈5道题,用时2h
算法·leetcode·职场和发展
我爱学嵌入式3 小时前
C 语言第 17 天学习笔记:从二级指针到内存布局的进阶指南
c语言·笔记·学习
Lukeding3 小时前
Magnetic-UI源码解析
算法
chirrupy_hamal4 小时前
排序算法详解
算法
落羽的落羽4 小时前
【C++】哈希表原理与实现详解
数据结构·c++
csdn_aspnet4 小时前
四边形面积
算法·四边形
快乐的划水a4 小时前
表驱动法-灵活编程范式
c++·链表