C语言数据结构---树

**1.**树概念及结构

1.1****树的概念

树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因****为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

注意:树形结构中,子树之间不能有交集,否则就不是树形结构

1.2 树的相关概念

**结点的度:**一个结点含有的子树的个数称为该结点的度; 如上图:A的为6

**叶结点或终端结点:**度为0的结点称为叶结点; 如上图:B、C、H、I...等结点为叶结点

**非终端结点或分支结点:**度不为0的结点; 如上图:D、E、F、G...等结点为分支结点

**双亲结点或父结点:**若一个结点含有子结点,则这个结点称为其子结点的父结点; 如上图:A是B的父结点

**孩子结点或子结点:**一个结点含有的子树的根结点称为该结点的子结点; 如上图:B是A的孩子结点

**兄弟结点:**具有相同父结点的结点互称为兄弟结点; 如上图:B、C是兄弟结点

**树的度:**一棵树中,最大的结点的度称为树的度; 如上图:树的度为6

**结点的层次:**从根开始定义起,根为第1层,根的子结点为第2层,以此类推;

**树的高度或深度:**树中结点的最大层次; 如上图:树的高度为4

**堂兄弟结点:**双亲在同一层的结点互为堂兄弟;如上图:H、I互为兄弟结点

**结点的祖先:**从根到该结点所经分支上的所有结点;如上图:A是所有结点的祖先

**子孙:**以某结点为根的子树中任一结点都称为该结点的子孙。如上图:所有结点都是A的子孙

**森林:**由m(m>0)棵互不相交的树的集合称为森林;

1.3****树的表示

树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,既然保存值域,也要保存结点和结点之间****的关系,实际中树有很多种表示方式如:双亲表示法,孩子表示法、孩子双亲表示法以及孩子兄弟表示法 等。我们这里就简单的了解其中最常用的孩子兄弟表示法

复制代码
typedef int DataType;
struct Node
{
   struct Node* firstChild1; // 第一个孩子结点
   struct Node* pNextBrother; // 指向其下一个兄弟结点
   DataType data; // 结点中的数据域
};

2.二叉树概念及结构

2.1概念

一棵二叉树是结点的一个有限集合,该集合:

1. 或者为空

2. 由一个根结点加上两棵别称为左子树和右子树的二叉树组成

从上图可以看出:

  1. 二叉树不存在度大于2的结点

  2. 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树

注意:对于任意的二叉树都是由以下几种情况复合而成的:

2.2 特殊的二叉树:

**1. 满二叉树:**一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是 说,如果一个二叉树的层数为K,且结点总数是2,则它就是满二叉树。

**2. 完全二叉树:**完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K 的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对 应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。

2.3 二叉树的性质

  1. 若规定根结点的层数为1,则一棵非空二叉树的第i层上最有 个个结点.

  2. 若规定根结点的层数为1,则深度为h的二叉树的最大结点数是 .

  3. 对任何一棵二叉树, 如果度为0其叶结点个数为 , 度为2的分支结点个数为 ,则有 = +1

3.二叉树的顺序结构及实现

3.1 二叉树的顺序结构

普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统 虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。

3.2二叉树的实现

创建二叉树的结构

复制代码
typedef struct Tree
{
    struct Tree *left;
    struct Tree *right;
    int data; 
}T;

创建二叉树的叶子结点

复制代码
T* newtree(int x)
{
  
    T *tree = (T *)malloc(sizeof(int) );
    if (tree == nullptr)
    {
        perror("fail malloc");
        return;
    }
    tree->left=nullptr;
    tree->right=nullptr;
    tree->data=x;
    return tree;
}

形成一棵二叉树树

复制代码
T* tee()
{
    T *tree1 = newtree(1);
    T *tree2= newtree(2);
    T *tree3 = newtree(3);
    T *tree4 = newtree(4);
    T *tree5 = newtree(5);
    T *tree6 = newtree(6);
    tree1->left=tree2;
    tree1->right=tree4;
    tree2->left=tree3;
    tree4->left=tree5;
    tree4->right=tree6;
    return tree1; 
}

前序遍历

复制代码
//根 左 右
void Preoder(T*tree)
{
   if(tree==nullptr)
   {
    printf("N ");
    return ;
   }
   cout<<tree->data<<endl;
   Preoder(tree->left);
   Preoder(tree->right);
}
//  1 2 3 N N N 4 5 N N 6 N N

中序遍历

复制代码
//左 根 右
void Inorder(T*tree)
{
    if(tree==nullptr)
   {
    printf("N ");
    return ;
   }
    Preoder(tree->left);
   cout<<tree->data<<endl;
   Preoder(tree->right);
}
//N 3 N 2 N 1 N 5 N 4 N 6 N

后序遍历

复制代码
//左 右 根
void odrer(T*tree)
{
      if(tree==nullptr)
   {
    printf("N ");
    return ;
   }
    Preoder(tree->left);
    Preoder(tree->right);
    cout<<tree->data<<endl;
}
// N N 3 N 2 N N 5 N N 6 4 1

统计节点总数

复制代码
int treesize(T *tree)
{

    return tree == nullptr ? 0 : treesize(tree->left) +
    treesize(tree->right) + 1;
}

统计叶子节点数

复制代码
int TreeLeafSize(T*tree)
{
	if (tree == NULL)
		return 0;

	if (tree->left == NULL && tree->right == NULL)
		return 1;

	return TreeLeafSize(left) + TreeLeafSize(right);
}

树的高度

复制代码
int TreeHeight(T *tree)
{
    if (tree == NULL)
        return 0;

    int leftH = TreeHeight(tree->left);
    int rightH = TreeHeight(tree->right);

    return leftH > rightH ? leftH + 1 : rightH + 1;
}

查找第K层有几个结点

复制代码
//查找第K层有几个结点  查找第三层为例
int Find(T*tree,int k)
{
    if (tree == NULL)
        return 0;
    if(k==1)
    {
        return 1;
    }
    return Find(tree->left,k-1)+
    Find(tree->right,k-1);
}

查找某节点

复制代码
//查找x结点  以5结点为例
T* treeFind(T*tree,int x)
{
    if (tree == NULL)
        return 0;
          if(tree->data ==x )
    {
        return tree;
    }
    //遍历树的左节点
    T* ret= treeFind(tree->left,x);
    if(ret)
    {
        return ret;
    }
    //遍历树的右节点
    T* ret1= treeFind(tree->right,x);
    if(ret1)
    {
        return ret1;
    }
    return nullptr;
}

判断完全二叉树

复制代码
// 判断完全二叉树
bool isCompleteTree(T* tree)
{
    if (tree == NULL)
        return true;

    T* queue[1000];
    int front = 0, rear = 0;
    queue[rear++] = tree; // 把 1 入队
    bool meetNull = false;

    while (front < rear)
    {
        T* cur = queue[front++];//出队列    

        if (cur == NULL)
        {
            meetNull = true;
        }
        else
        {
            if (meetNull)
                return false;

            queue[rear++] = cur->left;
            queue[rear++] = cur->right;
        }
    }
    return true;
}

二叉树的销毁

复制代码
void Destroy(T *tree)
{
     if (tree == NULL)
        return ;
     Destroy(tree->left);
     Destroy(tree->right);
     free(tree);
}

4.前序遍历的数组"ABD##E#H##CF##G##"构建二叉树

复制代码
#include <iostream>
using namespace std;
// 创建单个树结构
typedef char BTDataType;
typedef struct BinaryTree
{
    struct BinaryTree* left;
    struct BinaryTree* right;
    BTDataType data;
} BTNode;
// 存数据的数组 数组长度  pi数组下标指针
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi)
{
    // 越界或为#  //越界是递归处理完所有字符的正常标志
    if (*pi >= n || a[*pi] == '#')
    {
        (*pi)++;
        return nullptr;
    }
    // 有数据建树 . 创建根节点
    BTNode* tree = new BTNode;
    tree->data = a[*pi];
    (*pi)++; // 用过了
    //  2. 递归建左子树
    tree->left = BinaryTreeCreate(a, n, pi);
    // 3. 递归建右子树
    tree->right = BinaryTreeCreate(a, n, pi);
    return tree;
}
void Preoder(BTNode* tree)
{
    if (tree == nullptr)
    {
        printf("# ");
        return;
    }
    cout << tree->data << endl;
    Preoder(tree->left);
    Preoder(tree->right);
}

int main()
{
    char str[] = "ABD##E#H##CF##G##";
    int n = sizeof(str) / sizeof(str[0]) - 1; // 字符串长度
    int i = 0;

    BTNode* tree = BinaryTreeCreate(str, n, &i);
    cout << "二叉树构建完成!" << endl;
    cout << "打印二叉树: " << endl;
    Preoder(tree);
    return 0;
}
相关推荐
m0_734998012 小时前
Day 26
数据结构·c++·算法
励志的小陈3 小时前
复杂度算法题——旋转数组(三种思路)
c语言·数据结构·算法
Sirens.3 小时前
对顺序表以及双向链表的理解
数据结构·链表
㓗冽4 小时前
2026.03.27(第三天)
数据结构·c++·算法
七七肆十九4 小时前
PTA 7-38 数列求和-加强版
数据结构·算法
We་ct5 小时前
LeetCode 4. 寻找两个正序数组的中位数:二分优化思路详解
前端·数据结构·算法·leetcode·typescript·二分
计算机安禾6 小时前
【数据结构与算法】第10篇:项目实战:学生信息管理系统(线性表版)
开发语言·数据结构·算法·visual studio
xsyaaaan7 小时前
leetcode-hot100-二叉树
数据结构·leetcode
xiaoye-duck7 小时前
《算法题讲解指南:优选算法-哈希表》--58.存在重复元素I,59.存在重复元素II,60.字母异位词分组
数据结构·c++·哈希算法