万字教你入门数据结构(C语言)二叉树

  1. 树的概念和结构
  2. 树的表示 孩子兄弟表示法
  3. 二叉树概念及其结构
  4. 堆的概念 堆的实现 
  5. 大堆 小堆 堆排序 和TopK问题
  6. 链式二叉树概念 及其结构实现
  • 树的概念和结构

树 是一种非线性的数据结构 任意一棵树都会被分解成 根 和 N颗子树(N >= 0)

即 大问题分成子问题 不断分 这种递归思想 

下图 是以R为根(root) 有三颗子树的 树

树 与 非树 的区别

一棵N个节点的树有N-1条边  即 子树是不相交的  相交的则是图

 

树的性质 和一些名词解释

节点的度:一个节点含有的子树的个数

叶节点(叶子)终端:度为0的节(叶子节点)

分支节点:度不为0的节点

父节点:如上上图 树中R是a的父节点

子节点:如上上图 树中a是R的子节点

兄弟节点:具有相同父节点的节点 互称为兄弟节点

树的度: 一棵树中最大的节点的度 称为树的度

 节点的层次:从根开始定义起 根为第一层(主流说法)

//为什么数组从0开始 而不从1开始 因为数组需要解引用 而树 需要用0来表示空树 所有空树的高度为0 会产生歧义

树的高度或深度:树中节点的最大层次

堂兄弟节点:双亲在同一层的节点互称为堂兄弟

节点的祖先:从根到该节点所在的分支上的所有节点

子孙:以节点为根的子树中任意节点

树的表示 代码表示

struct TreeNode
{
    int data;
    //度该如何定义
    struct TreeNode*child1;
    //主要问题 我们不知道度的多少 
    //这样造少了不行 造多了会造成指针浪费
    //一般对于不确定的空间的 我们会有 顺序表 但C会很麻烦 C++会方便很多
    Seqlist child;
    vector <struct TreeNode*>child;
}
复习下 数组指针:一个指针指向一个数组
      指针数组:一个数组存储指针元素
struct TreeNode* Childs[N];//指针数组

如何去表示树呢 度的问题如何解决呢    这时候 出现了 《孩子兄弟表示法》这种方法完美的解决了这个问题

struct TreeNode //孩子兄弟表示法
{
    int data;
    struct TreeNode* child;
    struct TreeNode* brother;
}
树形结构必须一层一层走;用两个指针表示出任意多个孩子
《左孩子右兄弟》
父亲(root)指向左边的第一个孩子 让第一个孩子去指向他的兄弟

 

struct TreeNode //孩子兄弟表示法
{
    int data;
    struct TreeNode* child;
    struct TreeNode* brother;
};

Linux树状目录结构 也是一种树

 

  • 二叉树概念及其结构

而在实际运用中 真正实用的树 是 二叉树 即是度最大为2的树

 

二叉树 分为两大类 满二叉树 和 完全二叉树 

 

满二叉树 即是 每一层都是满的 二叉树

完全二叉树  是 前N-1层是满的 最后一层可以不满 但是必须从左到右连续

接下来我们分别计算下 这两种二叉树的总节点个数

由图可知 第k层则是 2^(k-1) 高度h 的满二叉树

总节点=  2^0+2^1+2^2+2^3+...+2^(h-1) 利用错位相减法 可以得出

T(h) = 2^h - 1

反向推理一波 

假设满二叉树有N个节点

2^h-1 = N   h = log2(N+1)

而完全二叉树 由于本身性质 只能计算个范围

最多:2^h-1 

最少:2^(h-1)

1.若规定根节点的层数为1 则一颗非空二叉树的第i层上最多有2^(i-1)个节点

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

3.如果(度为0)叶子结点个数为n0 度为2的分支节点个数为n2 则有 n0 = n2 + 1

4.若规定根节点的层数为1 具有n个节点的满二叉树的深度 h= log2(n+1)

  • 堆的概念 堆的实现 

介绍了这么久的二叉树 那二叉树有什么用呢 

二叉树分为 顺序存储 和 链式存储

顺序存储 即是 数组存储的 完全二叉树 就是 《堆》!

堆是一种完全二叉树  而满二叉树 是 一种特殊的完全二叉树(第n-1层是满的 最后一层必须连续)

只有堆是由顺序结构来实现的 其他二叉树会造成空间浪费

堆分为两大类 大堆 和 小堆

大堆:树中所有父亲都大于等于孩子

小堆:树中所有父亲都小于等于孩子

 这是堆的逻辑结构 而实际物理结构是 一个数组

 

那数组是如何表示二叉树的呢

孩子和父亲下标的关系

leftchild = parent*2 +1 

rightchild = parent*2 +2

parent = (child - 1)/2

左孩子一定是奇数位

右孩子一定是偶数位 

那随便给你个数组 一定判断是否为堆?

不能; 但一定是完全二叉树

以下是堆的 实现代码

typedef int HPDatatype;
typedef struct Heap
{
    HPDatatype* a;
    int size ;
    int capacity;
}HP;

void HeapInit(HP* php);
void HeapPush(HP* php,HPDatatype x);
void HeapPop(HP* php);
void HeapDestroy(HP* php);
void HeapPrint(HP* php);
HPDatatype HeapTop(HP* php);
bool HeapEmpty(HP* php);
void HeapCreate (HP* php,HPDatatype* a, int size);
void AdjustDown(HPDatatype* a,int size, int n);
void AdjustUp(HPDatatype* a,int child);
void Swap(HPDatatype* p1, HPDatatype* p2);


#include "Heap.h"
void Swap(HPDatatype* p1, HPDatatype* p2)
{
    HPDatatype tmp = *p1;
    *p1 = *p2;
    *p2 = tmp;
}
void AdjustDown(HPDatatype* a,int size, int n)//size 个数 n 初始位置
{
    /*
    int parent = n;
    int leftchild = 2*parent+1;
    int rightchild = 2*parent+2;
    while(leftchild < size && rightchild < size)
    {
        if(a[leftchild] > a[rightchild])
        {
            Swap(&a[leftchild], &a[parent]);
            parent = leftchild;
        }
        else
        {
            Swap(&a[rightchild], &a[parent]);
            parent = rightchild;
        }
        
        leftchild = 2*parent+1;
        rightchild = 2*parent+2;
    }
    另一种写法 */
    int parent = n;
    //默认左孩子最大
    int child = parent*2 +1;
    while(child < size)
    {
        if(child+1 < size && a[child+1] < a[child]) //特殊情况 万一没有右孩子呢?
        {
            child++;
        }//如果右孩子大 就变成右孩子
        
        if(a[child] < a[parent])//建立小堆
        {
            //如果孩子大于父亲 则交换
            Swap(&a[child], &a[parent]);
            //继续调整
            parent = child;
            child = parent * 2+1;
        }
        else
        {
            break;
        }
    }
}
void AdjustUp(HPDatatype* a,int child)
{
    int parent = (child-1)/2;
    while(child > 0)
    {
        if(a[child] > a[parent])//如果孩子大于父亲 //这是大堆 如果要小堆 if(a[child] < a[parent])即可
        {
            Swap(&a[child],&a[parent]);//交换
            child = parent;
            parent = (child - 1)/2;
        }//交换完后 继续判断
        else
        {
            break;
        }
    }
}
void HeapInit(HP* php)
{
    assert(php);
    php->a = NULL;
    php->capacity = php->size = 0;
}

void HeapPush(HP* php,HPDatatype x)
{
    assert(php);
    //检查扩容
    if(php->size == php->capacity)
    {
        int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;
        HPDatatype* tmp = (HPDatatype*)realloc(php->a, sizeof(HPDatatype)* newcapacity);
        //检查是否成功
        if(tmp == NULL)
        {
            perror("realloc fail");
            exit(-1);
        }
        php->a = tmp;
        php->capacity = newcapacity;
    }
    //插入
    php->a[php->size] = x;
    php->size++;
    //向上调整
    AdjustUp(php->a,php->size-1);
}

void HeapDestroy(HP* php)
{
    assert(php);
    php->size = php->capacity = 0;
    free(php->a);
    php->a = NULL;
   
}

void HeapPrint(HP* php)
{
    for (int i = 0; i < php->size; i++)
    {
        printf("%d ",php->a[i]);
    }
    printf("\n");
}

void HeapPop(HP* php)
{
    assert(php);
    assert(php->size >0);
    Swap(&php->a[0], &php->a[php->size-1]);
    php->size--;
    
    AdjustDown(php->a,php->size,0);
}

HPDatatype HeapTop(HP* php)
{
    assert(php);
    assert(php->size > 0);
    
    return php->a[0];
}

bool HeapEmpty(HP* php)
{
    return php->size == 0;
}

void HeapCreate (HP* php,HPDatatype* a, int size)
{
    assert(php);
    php->a = (HPDatatype*)malloc(sizeof(HPDatatype)* size);
    //检查
    memcpy(php->a, a, sizeof(HPDatatype)*size);
    php->size = php->capacity = size;
    //建堆算法
    for(int i = (size-1-1)/2 ; i >= 0 ; i--)
    {
        AdjustDown(php->a, size, i);
    }
}

注意事项 堆的push 和 pop需要 向上调整和 向下调整算法 非常重要!!!

 

 堆排序

如果我们要升序 要建大堆 如果要降序 则建小堆 

void test3(void)
{
    int array[] = {27,15,19,18,28,34,65,49,25,37};
   // HP hp;
   // HeapCreate(&hp, array, sizeof(array)/sizeof(int));
    HeapSort(array,sizeof(array)/sizeof(int));
    
    for (int i = 0; i < sizeof(array)/sizeof(int); i++)
    {
        printf("%d ",array[i]);
    }
    //
    //HeapPrint(&hp);
}
void HeapSort(HPDatatype* a,int n)
{
    /*
    for(int i = 0; i < n ; i++)
    {
        AdjustUp(a, i);
    }//向上调整
    */
    for(int i  = (n-1-1)/2 ; i >= 0 ; i--)
    {
        AdjustDown(a, n, i);
    }//确实建立个大堆 但没有排序
    //现在来实现排序功能
    
    int end = n-1;
    while(end > 0)
    {
        Swap(&a[end], &a[0]);
        AdjustDown(a, end, 0);
        --end;//注意end位置 变化
    }
     
}

TopK问题 

topk问题即是 求数据中前k个最大的元素或者最小的元素 就像现实生活中 专业前10名 世界500强 福布斯富豪榜类似

对于topk问题 最简单粗暴的方法就是排序 但如果数据量非常大 巨大 最佳的方法还是用堆来解决

N个数找最大的前k个

1.建立一个N个数的大堆 popk次依次取堆顶

但如果N很大 有10亿个数 那该怎么办呢

2.此时我们需要建一个 k个数的 小堆* 依次遍历数据 比堆顶数据大的 就替换堆顶 再向下调整

最后最大的k个元素就在 这个小堆里头了

这两种方法在性能上没有太大区别 但在空间复杂度上差别甚大

为什么不能建大堆 因为如果最大的数先进了堆会 阻碍剩下的数进入 建小堆 让大的全都沉在底下

  • 链式二叉树概念 及其结构实现  

接下来我们进入到链式二叉树的学习 顾名思义 链式二叉树的存储方式 是 指针

在链式二叉树的学习里头我们不会像之前的数据结构学习那样 学习他的增删查改 因为这样毫无意义 那链式二叉树的意义在于哪呢 在于 《搜索》!!!

二叉树的遍历 分为两种 深度优先遍历 和 广度优先遍历

1.深度优先遍历 对每一个可能的分支路径深入到不能在深入为止 而去每个节点都只能访问一次

可细分为 前序遍历 中序遍历 后序遍历

2.广度优先遍历 又称为层序遍历 从上往下对 每一层依次访问

 什么是 前序遍历 中序遍历 后序遍历?

前序遍历 中序遍历 后序遍历 又可称为 先根遍历 中根遍历 后根遍历

即 任意一颗树 = 根 和子树 

而前序遍历思想为  根->左子树->右子树 其他两种类似

void PrevOrder(BTNode* root)//前序遍历
{
    if(root == NULL)
    {
        printf("NULL->");
        return ;
    }
    
    printf("%c->",root->data);
    PrevOrder(root->left);
    PrevOrder(root->right);
}

BTNode* BuyNode(BTdatatype x)
{
    BTNode* node = (BTNode*)malloc(sizeof(BTNode));
    if(node == NULL)
    {
        perror("malloc fail");
        exit(-1);
    }
    //初始化
    node->data = x;
    node->left = NULL;
    node->right = NULL;
    
    return node;
}

//
void InOrder(BTNode* root)//中序遍历
{
    if(root == NULL)
    {
        printf("NULL->");
        return ;
    }
    
    
    InOrder(root->left);
    printf("%c->",root->data);
    InOrder(root->right);
}
void PostOrder(BTNode* root)//后序遍历
{
    if(root == NULL)
    {
        printf("NULL->");
        return ;
    }
    
    
    PostOrder(root->left);
    
    PostOrder(root->right);
    printf("%d->",root->data);
}
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include "Queue.h"

typedef int BTdatatype;//树的节点指针
typedef struct Node
{
    BTdatatype data;
    struct Node* left;
    struct Node* right;
    
}BTNode;



void PrevOrder(BTNode* root);//前序遍历
void InOrder(BTNode* root);//中序遍历
void PostOrder(BTNode* root);//后序遍历

那层序遍历呢?如何实现呢

层序遍历怎么走 一层一层的从左到右的走 层序遍历就不是用递归思想的了

走层序遍历 需要用一个队列(先进先出)

 

root不为空则入队 队列不为空 把root pop出来 将root的两个子树 也就是第二层带进去

后续也是这样操作 直到队列为空就结束

《出上一层 带下一层》 

void BinaryTreeLevelOrder(BTNode* root)
{
    Queue q;//定义一个队列
    QueueInit(&q);
    if(root)
        QueuePush(&q, root);
    ///
    while (!QueueEmpty(&q))
    {
        BTNode* front = QueueFront(&q);
        printf("%d ",front->data);
        QueuePop(&q);
        if(front->left)//如果左不为空 就把左子树带进队列
        {
            QueuePush(&q, front->left);//
            //  
        }
        if(front->right)
        {
            QueuePush(&q, front->right);
        }
        
    }
    printf("\n");
    
}
void Test2(void)
{
    BTNode* n1 = BuyNode(1);
    BTNode* n2 = BuyNode(2);
    BTNode* n3 = BuyNode(3);
    BTNode* n4 = BuyNode(4);
    BTNode* n5 = BuyNode(5);
    BTNode* n6 = BuyNode(6);//创造节点
    
    n1->left = n2;
    n2->left = n3;
    n1->right = n4;
    n4->left = n5;
    n4->right = n6;
    
    BTNode* root = BinaryTreeFind(n1, 6);
    printf("%d\n",root->data);
    BinaryTreeLevelOrder(n1);
}

接下来就是链式二叉树的实现 和相关功能的实现

头文件

#ifndef Binary_tree_h
#define Binary_tree_h

typedef int BTdatatype;//树的节点指针
typedef struct Node
{
    BTdatatype data;
    struct Node* left;
    struct Node* right;
    
}BTNode;
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include "Queue.h"


void PrevOrder(BTNode* root);//前序遍历
void InOrder(BTNode* root);//中序遍历
void PostOrder(BTNode* root);//后序遍历
BTNode* BuyNode(BTdatatype x);
int TreeSize1(BTNode* root);//
int TreeSize2(BTNode* root);//试下静态变量是否能解决
void TreeSize3(BTNode* root);
BTNode* rebulidTree(char* str,int* pi);
void BinaryTreeDestory(BTNode* root);
BTNode* BinaryTreeFind(BTNode* root , int x);//查找
void BinaryTreeLevelOrder(BTNode* root);//层序遍历
int BinaryTreeComplete(BTNode* root);//判断是否为完全二叉树
//不能用数量关系来判断 满二叉树和完全二叉树
//在已知高度h的情况下 2^(h-1)是满二叉树 而完全二叉树是个范围
//怎么做呢 使用层序遍历 队列的方法
/*
 需要一个队列 队列里存什么呢 节点的地址
 如果root不为0 即插入队列中
 要是队列不为空 将队头的元素取出 并打印 再删除
 进入递归
 如果左不为空 就把左子树带入队列
 右边也是如此
 
 */
#endif /* Binary_tree_h */
/*
 // 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
 BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi);
 // 二叉树销毁
 void BinaryTreeDestory(BTNode** root);
 // 二叉树节点个数
 int BinaryTreeSize(BTNode* root);
 // 二叉树叶子节点个数
 int BinaryTreeLeafSize(BTNode* root);
 // 二叉树第k层节点个数
 int BinaryTreeLevelKSize(BTNode* root, int k);
 // 二叉树查找值为x的节点
 BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
 // 二叉树前序遍历
 void BinaryTreePrevOrder(BTNode* root);
 // 二叉树中序遍历
 void BinaryTreeInOrder(BTNode* root);
 // 二叉树后序遍历
 void BinaryTreePostOrder(BTNode* root);
 // 层序遍历
 void BinaryTreeLevelOrder(BTNode* root);
 // 判断二叉树是否是完全二叉树
 int BinaryTreeComplete(BTNode* root);
 */
//单值二叉树 二叉树的最大深度 检查两个树是否相同

源文件 

#include "Binary_tree.h"
#include"Queue.h"


void PrevOrder(BTNode* root)//前序遍历
{
    if(root == NULL)
    {
        printf("NULL->");
        return ;
    }
    
    printf("%c->",root->data);
    PrevOrder(root->left);
    PrevOrder(root->right);
}

BTNode* BuyNode(BTdatatype x)
{
    BTNode* node = (BTNode*)malloc(sizeof(BTNode));
    if(node == NULL)
    {
        perror("malloc fail");
        exit(-1);
    }
    //初始化
    node->data = x;
    node->left = NULL;
    node->right = NULL;
    
    return node;
}

//
void InOrder(BTNode* root)//中序遍历
{
    if(root == NULL)
    {
        printf("NULL->");
        return ;
    }
    
    
    InOrder(root->left);
    printf("%c->",root->data);
    InOrder(root->right);
}
void PostOrder(BTNode* root)//后序遍历
{
    if(root == NULL)
    {
        printf("NULL->");
        return ;
    }
    
    
    PostOrder(root->left);
    
    PostOrder(root->right);
    printf("%d->",root->data);
}
int TreeSize1(BTNode* root)
{
    //遍历一遍且计数
    
    if(root == NULL)
    {
        //printf("NULL->");
        return 0;
    }
    
    //printf("%d->",root->data);
    int size = 0;
    size++;
    TreeSize1(root->left);
    TreeSize1(root->right);
    return size;
}
int TreeSize2(BTNode* root)
{
    //遍历一遍且计数
    
    if(root == NULL)
    {
        //printf("NULL->");
        return 0;
    }
    
    //printf("%d->",root->data);
    static int size = 0;
    size++;
    TreeSize2(root->left);
    TreeSize2(root->right);
    return size;
    
}

BTNode* rebulidTree(char* str,int* pi)
{
    if(str[*pi] == '#')
    {
        (*pi)++;
        return NULL;
    }
    //
    BTNode* root = (BTNode*)malloc(sizeof(BTNode));
    root->data = str[(*pi)++];
    
    root->left = rebulidTree(str, pi);
    root->right = rebulidTree(str, pi);
    
    return root;
}
/*
 void Inorder(BTnode* root)
 {
    if(root == NULL)
    {
        printf("NULL")
    }
    Inorder(root->left)
    printf(root->data);
    Inrder(root->right);
 
 }
 */
void BinaryTreeDestory(BTNode* root)
{
    //一个一个消除
    //assert(root);
    //只能后序遍历 先把左右消掉再消掉根
    if(root == NULL)
    {
        return;
    }
    
    BinaryTreeDestory(root->left);
    BinaryTreeDestory(root->right);
    
    free(root);
    root = NULL;//其实毫无意义 形参的改变是不会影响实参的
    
}
BTNode* BinaryTreeFind(BTNode* root , int x)//查找
{
    if(root == NULL)
    {
        return NULL;
    }
    if(root->data == x)
    {
        return root;
    }
    
    BTNode* ret1 = BinaryTreeFind(root->left, x);
    if(ret1)//如果ret1为空则返回空
        return ret1;
    
    BTNode* ret2 = BinaryTreeFind(root->right, x);
    if(ret2)
        return ret2;
    
    return NULL;
}

void BinaryTreeLevelOrder(BTNode* root)
{
    Queue q;//定义一个队列
    QueueInit(&q);
    if(root)
        QueuePush(&q, root);
    ///
    while (!QueueEmpty(&q))
    {
        BTNode* front = QueueFront(&q);
        printf("%d ",front->data);
        QueuePop(&q);
        if(front->left)//如果左不为空 就把左子树带进队列
        {
            QueuePush(&q, front->left);//笑死 这里找这种傻逼错误找半天 调半天
            //  打起精神起来  front->data这种怎么可以写出来
        }
        if(front->right)
        {
            QueuePush(&q, front->right);
        }
        
    }
    printf("\n");
    
}

int BinaryTreeComplete(BTNode* root)//判断是否为完全二叉树
{
    Queue q;
    QueueInit(&q);
    if(root)//  如果root不为空 则插入队列
        QueuePush(&q, root);
    //分两部
    while (!QueueEmpty(&q))//检查队列是否为空 不为空则
    {
        BTNode* front = QueueFront(&q);//取队头
        QueuePop(&q);
        if(front == NULL)
        {
            break;//如果取出的是空 则停止
        }
        else
        {
            QueuePush(&q, front->left);
            QueuePush(&q, front->right);
            //如果不为空 则继续插入 出上层带下层
        }
    }
    
    
    ///退出后 检查是否后面还存在节点 存在即不是完全二叉树
    while (!QueueEmpty(&q))
    {
        BTNode* front = QueueFront(&q);
        QueuePop(&q);
        
        if(front != NULL)
        {
            QueueDestroy(&q);//检查非空出现
            return false;
        }
        
    }
    //没检查出来
    QueueDestroy(&q);
    return true;
}

主函数

#include <stdio.h>
#include "Binary_tree.h"
//#include "Binary_tree"
int TreeKlevelSize1(BTNode* root,int k)
{
    if(root == NULL)
    {
        return  0;
    }
    if(k == 1)
    {
        return 1;
    }
    return TreeKlevelSize1(root->left, k-1) && TreeKlevelSize1(root->right, k-1);
}
int TreeKlevelSize2(BTNode* root,int k)
{
    if(root == NULL)
    {
        return  0;
    }
    if(k == 1)
    {
        return 1;
    }
    return TreeKlevelSize2(root->left, k-1) + TreeKlevelSize2(root->right, k-1);
}
int TreeHeight(BTNode* root)
{
    //取左子树和右子树最高的那位去+1
    if(root == NULL)
    {
        //如果他是叶子节点则返回
        return 0;
    }
    int leftHeight = TreeHeight(root->left);
    int rightHeight = TreeHeight(root->right);
    
    return leftHeight > rightHeight ? leftHeight+1 : rightHeight+1;
}
int size = 0;//设置一个全局变量
void TreeSize3(BTNode* root)
{
    if(root == NULL)
    {
        //printf("NULL->");
        return ;
    }
    
    //printf("%d->",root->data);
    
    size++;
    TreeSize3(root->left);
    TreeSize3(root->right);
    
}
int TreeSize(BTNode* root)
{
    return root == NULL ? 0:TreeSize(root->left)+TreeSize(root->right)+1;
}
/*
 if(root == NULL)
 {
    return 0;
 }
 
 return Treesize(root->left)+Treesize(root->right)+1;
 */
int TreeLeafSize(BTNode* root)
{
    if(root == NULL)
    {
        return 0;
    }
    if(root->left == NULL && root->right == NULL)
    {
        return 1;
    }
    
    return TreeLeafSize(root->left)+TreeLeafSize(root->right);
}
void Test1(void)
{
    char str[100] ;
    printf(">\n");
    scanf("%s",str);
    int i = 0;
    BTNode* root = rebulidTree(str, &i);
    
    //PrevOrder(root);
    InOrder(root);
}
void Test2(void)
{
    BTNode* n1 = BuyNode(1);
    BTNode* n2 = BuyNode(2);
    BTNode* n3 = BuyNode(3);
    BTNode* n4 = BuyNode(4);
    BTNode* n5 = BuyNode(5);
    BTNode* n6 = BuyNode(6);//创造节点
    
    n1->left = n2;
    n2->left = n3;
    n1->right = n4;
    n4->left = n5;
    n4->right = n6;
    
    BTNode* root = BinaryTreeFind(n1, 6);
    printf("%d\n",root->data);
    BinaryTreeLevelOrder(n1);
}
void Test3(void)
{
    BTNode* n1 = BuyNode(1);
    BTNode* n2 = BuyNode(2);
    BTNode* n3 = BuyNode(3);
    BTNode* n4 = BuyNode(4);
    BTNode* n5 = BuyNode(5);
    BTNode* n6 = BuyNode(6);//创造节点
    
    n1->left = n2;
    n2->left = n3;
    n1->right = n4;
    n2->right = n5;
    n4->left = n6;
    //
    printf("%d\n",BinaryTreeComplete(n1));
}
int main(int argc, const char * argv[])
{
    //BTNode* root;
    /*
    BTNode* n1 = BuyNode(1);
    BTNode* n2 = BuyNode(2);
    BTNode* n3 = BuyNode(3);
    BTNode* n4 = BuyNode(4);
    BTNode* n5 = BuyNode(5);
    BTNode* n6 = BuyNode(6);//创造节点
   // BTNode* n7 = BuyNode(7);
    
    //连接节点
    n1->left = n2;
    n2->left = n3;
    n1->right = n4;
    n4->left = n5;
    n4->right = n6;
    //n3->left = n7;
    //
   // PostOrder(n1);
 //   printf("size = %d",TreeSize1(n1));//这种是错误的 递归创造栈帧 每个size都是独自的size无法叠加
   // printf("size = %d\n",TreeSize2(n1));//
    //size = 0;你都没有办法 去重新初始化他
    //printf("size = %d\n",TreeSize2(n1));//也不对 size放在静态区
    //
    /*
    TreeSize3(n1);
    printf("%d\n",size);
    size = 0;
    TreeSize3(n1);
    printf("%d\n",size);
     */
    //printf("%d\n",TreeSize(n1));
    //printf("%d\n",TreeLeafSize(n1));
    //printf("%d\n",TreeHeight(n1));
    //printf("%d\n",TreeKlevelSize1(n1, 3));
   // printf("%d\n",TreeKlevelSize2(n1, 3));
    //Test1();
    //Test2();
    Test3();
    return 0;
}

好啦 看到这里 二叉树学习 就算入门了 喜欢的观众不妨来个一键三连 我们下期再见 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值