- 树的概念和结构
- 树的表示 孩子兄弟表示法
- 二叉树概念及其结构
- 堆的概念 堆的实现
- 大堆 小堆 堆排序 和TopK问题
- 链式二叉树概念 及其结构实现
-
树的概念和结构
树 是一种非线性的数据结构 任意一棵树都会被分解成 根 和 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;
}
好啦 看到这里 二叉树学习 就算入门了 喜欢的观众不妨来个一键三连 我们下期再见