数据结构 二叉树

简介: 数据结构 二叉树

二叉树

第一题:二叉树叶子结点个数

[问题描述]

编写递归算法,计算二叉树中叶子结点的数目。

[输入]

一棵二叉树的结点若无子树,则可将其子树看作“.”,输入时,按照先序序列的顺序输入该结点的内容。对下图,其输入序列为ABD…EH…CF.I…G…。

[输出]

该二叉树叶子节点个数

[存储结构]

采用二叉链表存储。

[算法的基本思想]

创建二叉树:采用递归的方法建立一颗二叉树,再用递归的方法进行叶子节点的计数

#include <stdio.h>
#include <malloc.h>
#define NULL 0 
typedef struct BTNode{
  char a;
  struct BTNode *lchild;
  struct BTNode *rchild;
}BTNode, *node;
node createBTNode(node p){
  //创建树,按照先序遍历 
  char x;
  scanf("%c", &x);
  if(x == '.'){
    //是否满足为空树的情况 
    p = NULL;
  }
  else{
    p = (node)malloc(sizeof(BTNode));
    p->a = x;
    p->lchild = createBTNode(p->lchild);
    p->rchild = createBTNode(p->rchild);
  }
  return p;
}
int count =0; //count用来计数 
void num(node p){
  //递归遍历,记录叶子节点个数 
  if(p){
    if((p->lchild == NULL) && (p->rchild) == NULL)
    count++;
    num(p->lchild);
    num(p->rchild);
  }
}
int main(){
  printf("请输入树:");
  node p = createBTNode(p);
  num(p);
  printf("叶子节点个数为:%d", count);
}

结果演示:

image.png

结果与分析:

优点:通过递归函数简洁明了的完成了实验要求,时间复杂度:O(n),空间复杂度:O(n),n为创建树的结点个数。

第二题:二叉树先序序列查找

[问题描述]

编写递归算法,在二叉树中求位于先序序列中第K个位置的结点。

[输入]

一棵二叉树的结点若无子树,则可将其子树看作“.”,输入时,按照先序序列的顺序输入该结点的内容。对下图,其输入序列为ABD…EH…CF.I…G…,再输入数字K。

[输出]

位于先序遍历的第K个位置的结点

[存储结构]

采用二叉链表存储。

[算法的基本思想]

创建二叉树:采用递归的方法建立一颗二叉树,再通过递归的方式得到先序序列中第K个位置的元素

#include<stdio.h>
#include<malloc.h>
#define NULL 0
typedef struct BTNode{
  char a;
  struct BTNode *lchild;
  struct BTNode *rchild;
}BTNode, *node;
node createBTNode(node &p){
  //创建二叉树 
  char x;
  scanf("%c", &x);
  if (x == '.'){
    p = NULL;
  }
  else{
    p = (node)malloc(sizeof(BTNode));
    p->a = x;
    p->lchild = createBTNode(p->lchild);
    p->rchild = createBTNode(p->rchild);
  }
  return p;
}
char pre[100]; //创建字符串数组,存储先序生成的序列 
int i = 0;//计数器 
void visit(node p) {
  //将先序序列存入字符串数组 
  pre[i] = p->a;
  i++;
}
void preorder(node p){
  //先序遍历 
  if(p != NULL){
    visit(p);
    preorder(p->lchild);
    preorder(p->rchild);
  }
}
int main(){
  printf("请输入树:"); 
  node p = createBTNode(p);
  preorder(p);
  printf("请输入先序遍历查找的K位置元素:");
  int k;
  scanf("%d", &k);
  printf("先序遍历K位置元素:%c", pre[k - 1]);
}

结果演示:

image.png

结果与分析:

优点:通过递归实现先序遍历,在先序遍历的同时将数据内容存入字符串,通过字符下标便可以查找元素,缺点:需要先将树的全部进行先序遍历,而且需要开辟新的空间用于存储字符串,时间复杂度:O(n),空间复杂度:O(n),n为创建树的结点个数。

第三题:非递归构造二叉树 + 层次遍历

[问题描述]

任意给定一棵二叉树。试设计一个程序,在计算机中构造该二叉树,并对它进行遍历。要求:使用非递归算法的算法实现。

[输入]

一棵二叉树的结点若无子树,则可将其子树看作“.”,输入时,按照前序序列的顺序输入该结点的内容。对下图,其输入序列为ABD…EH…CF.I…G…。

[输出]

进行遍历后得到的序列

[存储结构]

采用二叉链表存储。

[算法的基本思想]

采用栈的存储结构实现非递归的方法先序序列创建二叉树,再使用队列的存储结构实现非递归的层次遍历

#include<stdio.h>
#include<malloc.h>
#define NULL 0
#define MAXSIZE 10
typedef struct BTNode{
  char a;
  int flag; //flag=0左子树没有设置;flag=1左子树设置,右子树没有设置;flag=2出栈条件 
  struct BTNode *lchild;
  struct BTNode *rchild;
}BTNode, *node;
node createBTNode(node p){
  //创建二叉树,非递归算法 
  BTNode *stack[MAXSIZE];  //定义栈 
  int top = -1;  //初始化栈
  p = (node)malloc(sizeof(BTNode));  //创建根节点 
  char x;
  scanf("%c", &x);
  p->a = x;
  p->flag = 0;
  stack[++top] = p;  //根结点进栈 
  while(top != -1){
    char x;
    scanf("%c", &x);
    if(x == '.'){
      //“.”空结点的表示方式 
      if(stack[top]->flag == 0){
        stack[top]->flag = 1;
        stack[top]->lchild = NULL;
      }
      else if(stack[top]->flag == 1){
        stack[top]->flag = 2;
        stack[top]->rchild = NULL;
      }
    }
    else{
      node q = (node)malloc(sizeof(BTNode));
      q->a = x;
      q->flag = 0;
      if(stack[top]->flag == 0){
        //先插左子树 
        stack[top]->lchild = q;
        stack[top]->flag = 1;
        stack[++top] = q;
      }
      else if(stack[top]->flag == 1){
        //判断是否满足插入右子树的条件 
        stack[top]->rchild = q;
        stack[top]->flag = 2;
        stack[++top] = q;
      }
    }
    while(stack[top]->flag == 2){
      //判断是否满足出栈条件,满足则连续出栈 
      top--;
    }
  }
  return p;
}
void showBTNode(node p){
  //使用非递归,层次遍历进行实现
  BTNode *queue[MAXSIZE];
  int front = 0;
  int rear = 0;
  queue[rear++] = p; //根结点入队 
  while(front != rear){
    if(queue[front]->lchild != NULL){
      queue[rear++] = queue[front]->lchild;
    }
    if(queue[front]->rchild != NULL){
      queue[rear++] = queue[front]->rchild;
    }
    printf("%c", queue[front]->a);
    front++;
  }
} 
int main(){
  printf("请输入树:"); 
  node p = createBTNode(p);
  printf("层次遍历结果为:"); 
  showBTNode(p);
}

结果演示:

image.png

结果与分析:

优点:使用栈的存储结构实现了,非递归的二叉树创建,同时使用队列的数据结构实现了层次遍历,缺点代码难度较高,不易理解时间复杂度:O(n),空间复杂度:O(n)。

心得

  1. 因为树可以通过递归定义自身内容,所以解决树的数据结构问题通常也可以通过递归的函数来实现。
  2. 递归的算法可以使得代码简洁明了,在写递归函数时要明确结束条件,掌握递归函数的执行次序。
  3. 很多树的操作都可基于遍历的思想经行改变,例如第二题中使用先序遍历的思想,只需修改,visit()函数,便可以实现想要的功能。
  4. 通过手写栈的存储结构可以代替树的创建时的递归函数,要注意在第三题中需要设置flag的特殊二叉树结构体,方便判断是否每个点都被访问过,方便点插入位置,与出栈条件的判断。
  5. 通过队列的结构体,进行非递归的树的层次遍历。


目录
相关文章
|
14天前
|
存储 机器学习/深度学习
【数据结构】二叉树全攻略,从实现到应用详解
本文介绍了树形结构及其重要类型——二叉树。树由若干节点组成,具有层次关系。二叉树每个节点最多有两个子树,分为左子树和右子树。文中详细描述了二叉树的不同类型,如完全二叉树、满二叉树、平衡二叉树及搜索二叉树,并阐述了二叉树的基本性质与存储方式。此外,还介绍了二叉树的实现方法,包括节点定义、遍历方式(前序、中序、后序、层序遍历),并提供了多个示例代码,帮助理解二叉树的基本操作。
38 13
【数据结构】二叉树全攻略,从实现到应用详解
|
3月前
|
存储 算法
【数据结构和算法】--- 二叉树(4)--二叉树链式结构的实现(2)
【数据结构和算法】--- 二叉树(4)--二叉树链式结构的实现(2)
28 0
|
11天前
|
存储 算法 C语言
数据结构基础详解(C语言): 二叉树的遍历_线索二叉树_树的存储结构_树与森林详解
本文从二叉树遍历入手,详细介绍了先序、中序和后序遍历方法,并探讨了如何构建二叉树及线索二叉树的概念。接着,文章讲解了树和森林的存储结构,特别是如何将树与森林转换为二叉树形式,以便利用二叉树的遍历方法。最后,讨论了树和森林的遍历算法,包括先根、后根和层次遍历。通过这些内容,读者可以全面了解二叉树及其相关概念。
|
11天前
|
存储 机器学习/深度学习 C语言
数据结构基础详解(C语言): 树与二叉树的基本类型与存储结构详解
本文介绍了树和二叉树的基本概念及性质。树是由节点组成的层次结构,其中节点的度为其分支数量,树的度为树中最大节点度数。二叉树是一种特殊的树,其节点最多有两个子节点,具有多种性质,如叶子节点数与度为2的节点数之间的关系。此外,还介绍了二叉树的不同形态,包括满二叉树、完全二叉树、二叉排序树和平衡二叉树,并探讨了二叉树的顺序存储和链式存储结构。
|
11天前
|
存储 C语言
数据结构基础详解(C语言): 树与二叉树的应用_哈夫曼树与哈夫曼曼编码_并查集_二叉排序树_平衡二叉树
本文详细介绍了树与二叉树的应用,涵盖哈夫曼树与哈夫曼编码、并查集以及二叉排序树等内容。首先讲解了哈夫曼树的构造方法及其在数据压缩中的应用;接着介绍了并查集的基本概念、存储结构及优化方法;随后探讨了二叉排序树的定义、查找、插入和删除操作;最后阐述了平衡二叉树的概念及其在保证树平衡状态下的插入和删除操作。通过本文,读者可以全面了解树与二叉树在实际问题中的应用技巧和优化策略。
|
1月前
|
存储
【初阶数据结构篇】二叉树基础概念
有⼀个特殊的结点,称为根结点,根结点没有前驱结点。
|
1月前
|
存储 Linux Windows
【数据结构】二叉树
【数据结构】二叉树
|
1月前
|
存储 算法 Linux
【数据结构】树、二叉树与堆(长期维护)(1)
【数据结构】树、二叉树与堆(长期维护)(1)
|
1月前
|
算法
【数据结构】树、二叉树与堆(长期维护)(2)
【数据结构】树、二叉树与堆(长期维护)(2)
【数据结构】树、二叉树与堆(长期维护)(2)
|
1月前
|
算法 Java
数据结构二叉树
这篇文章讨论了数据结构中的二叉树,并提供了一个二叉树中序遍历的算法示例,包括给定二叉树的根节点返回中序遍历结果的Java代码实现。
数据结构二叉树