堆与链式二叉树

前言

本次文章主要讲的是数据结构中的堆与链式二叉树。在堆中我们会将一种排序,就是堆排序,它的效率很高的,是logn*n。在链式二叉树中我们会讲到很多OJ题,把递归这玩意玩的明明白白。

1.堆的实现

1.1头文件

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

1.2堆的销毁

// 堆的销毁
void HeapDestory(HP* php)
{
	assert(php);
	free(php->a);
	php->size = php->capacity = 0;
}

1.3向上调整算法

Swap(HPDataType* child, HPDataType* parent)
{
	HPDataType tmp = *child;
	*child = *parent;
	*parent = tmp;
}

AdjustUp(HPDataType* a, int child)
{
	//这里我们建立小堆
		//能这样干的前提,向上的都是小堆
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] < a[parent])
		{
			Swap(&a[child],&a[parent]);
		}
		else
		{
			break;
		}
		child = parent;
		parent = (child - 1) / 2;
	}
}

1.4堆的插入

// 堆的插入
void HeapPush(HP* php, HPDataType x)
{
	assert(php);
	if (php->capacity == php->size)
	{
		int new_capacity = php->capacity == 0 ? 4 : php->capacity * 2;
		HPDataType*p = realloc(php->a, sizeof(HPDataType) * new_capacity);
		if (p == NULL)
		{
			perror("HeapPush:");
			return;
		}
		php->a = p;
		php->capacity = new_capacity;
	}
	php->a[php->size] = x;
	php->size++;
	AdjustUp(php->a, php->size-1);
}

1.5向下调整算法

void AdjustDown(HPDataType*a, int n, int parent)
{
	int child = parent * 2 + 1;//先默认小的孩子为左孩子
	while (child < n)
	{
		if (child + 1 < n && a[child + 1] < a[child])
		{
			child++;
		}
		//开始调整
		if (a[parent] > a[child])
		{
			Swap(&a[parent], &a[child]);
		}
		else
		{
			break;
		}
		parent = child;
		child = child * 2 + 1;
	}
}

1.6堆的删除

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);//传入数组长度和要向下调整的元素下标
	//能这样干的前提,向下的都是小堆
}

1.7取堆顶的数据

// 取堆顶的数据
HPDataType HeapTop(HP* php)
{
	assert(php);
	assert(php->size > 0);
	return php->a[0];
}

1.8堆的数据个数

// 堆的数据个数
int HeapSize(HP* php)
{
	assert(php);
	return php->size;
}

1.9堆的判空

// 堆的判空
int HeapEmpty(HP* php)
{
	assert(php);
	return php->size == 0;
}

2.堆排序

2.1堆排序

法一

//堆排序
void HeapSort1(HPDataType* a, int n)//小堆就降序
{
	//首先要把这个数组变成堆才行
	//则从第一个元素开始就向上调整就可以了,因为向上调整的要求就是上面的为堆,所以从开头开始,或者从第二个开始,因为第一个已经是堆了
	for (int i = 2; i < n; i++)
	{
		AdjustUp(a, i);
	}
	//这样的话就变成堆了,这样的话第一个元素就是最小的了
	while (n > 0)
	{
		Swap(&a[0], &a[n - 1]);
		n--;//因为这样的话下一步向下调整就不会涉及到我的最小元素了
		//再对第一个元素进行向下调整
		AdjustDown(a, n, 0);//这样的话第二小的元素就跑到堆顶了
	}
}

法二

//堆排序
void HeapSort2(HPDataType* a, int n)//小堆就降序
{
	//第二个方法就是建堆的方法不一样罢了
	//倒着建堆,每一个都向下调整,因为向下调整的前提就是下面的为堆
	//而且从第一个非叶子节点开始建堆,因为一个叶子节点就已经是堆了
	for (int i =(n-1-1)/2; i >= 0; i--)
	{
		AdjustDown(a,n, i);
	}
	//这样的话就变成堆了,这样的话第一个元素就是最小的了
	while (n > 0)
	{
		Swap(&a[0], &a[n - 1]);
		n--;//因为这样的话下一步向下调整就不会涉及到我的最小元素了
		//再对第一个元素进行向下调整
		AdjustDown(a, n, 0);//这样的话第二小的元素就跑到堆顶了
	}
}

2.2创造数据

//创造10万个数据
void CreatData()
{
	FILE* pf = fopen("text.txt", "w");
	int n = 100000;
	srand((unsigned int)time(NULL));
	for(int i=0;i<n;i++)
	{
		int x = (rand() + i) % 100000;
		fprintf(pf, "%d\n", x);
	}
	fclose(pf);
}

2.3topk算法

//topk算法
void PrintTopK(int k)
{
	//找出前k个大的,而且空间复杂度为1
	//建立大小为k的堆,因为k远小于10万,所以视为常数
	//向下调整建立堆
	int* arr = (int*)malloc(sizeof(int)*k);
	//将前k个数据放入数组中
	FILE* pf = fopen("text.txt", "r");
	for (int i = 0; i < k; i++)
	{
		fscanf(pf, "%d", &arr[i]);
	}
	//将前k个数据建堆
	for (int i = (k - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(arr, k, i);
	}
	//现在堆最上面放的肯定是最小的
	//现在开始访问十万个数据,比堆顶大的,就放上去,并向下调整
	int x = 0;
	while (fscanf(pf, "%d", &x) != EOF)
	{
		if (x > arr[0])
		{
			arr[0] = x;
			AdjustDown(arr, k, 0);
		}
	}
	//打印出前k个最大的
	for (int i = 0; i < k; i++)
	{
		printf("%d ", arr[i]);
	}
}

3.链式二叉树的实现

3.1二叉树的创建

嗯二叉树的创建一定程度上是没有什么意义的,手搓就可以了
这里我们写头文件

typedef char BTDataType;

typedef struct BinaryTreeNode
{
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;

3.2二叉树销毁

// 二叉树销毁
void BinaryTreeDestory(BTNode** root)
{
	assert(root);
	BTNode* node = *root;
	if (node == NULL)
	{
		return;
	}
	BinaryTreeDestory(&node->left);
	BinaryTreeDestory(&node->right);
	free(node);
	//printf("free一次");
	node = NULL;
}

3.3二叉树节点个数

// 二叉树节点个数
int BinaryTreeSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	return 1+BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}

3.4二叉树叶子节点个数

// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	if (root->left == NULL && root->right == NULL)
	{
		return 1;
	}
	return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}

3.5二叉树第k层节点个数

// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
	//求第k层的话,递归的话,就是求子树第k-1层的节点个数,如果是第k层的,就返回1
	if (root == NULL)
	{
		return 0;
	}
	if (k == 1)
	{
		return 1;
	}
	return BinaryTreeLevelKSize(root->left, k - 1) + BinaryTreeLevelKSize(root->right, k - 1);
}

3.6二叉树查找值为x的节点

// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	//找节点为x的话,递归的话,就相当于返回子树不为NULL的某个返回值
	if (root == NULL)
	{
		return NULL;
	}
	if (root->data == x)
	{
		return root;
	}
	//先存下左右子树的返回值,不然会递归多次
	BTNode* root_left = BinaryTreeFind(root->left, x);
	BTNode* root_right = BinaryTreeFind(root->right, x);
	if (root_left == NULL)//说明左子树没有x的节点
	{
		return root_right;
	}
	else//两个都没有x的节点。就随便返回一个吧
	{
		return root_left;
	}
}

3.7二叉树前序遍历

// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root)
{
	//先访问根,就是先把根的东西写出来,最后再递归
	if (root == NULL)
	{
		printf("N ");
		return;
	}
	printf("%c ", root->data);
	BinaryTreePrevOrder(root->left);
	BinaryTreePrevOrder(root->right);
}

3.8二叉树中序遍历

// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
	//中间访问根,就是再中间把根的东西写出来,递归放两边
	if (root == NULL)
	{
		printf("N ");
		return;
	}
	BinaryTreeInOrder(root->left);
	printf("%c ", root->data);
	BinaryTreeInOrder(root->right);
}

3.9二叉树后序遍历

// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}
	BinaryTreePostOrder(root->left);
	BinaryTreePostOrder(root->right);
	printf("%c ", root->data);
}

3.10层序遍历

// 层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
	//先把根入队列
	//然后出一个队列就入其孩子队列
	Queue q;
	QueueInit(&q);
	if (root == NULL)
	{
		return;
	}
	QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		//出一个
		BTNode* ret = QueueFront(&q);
		QueuePop(&q);
		printf("%c ", ret->data);
		//如果孩子不为空就入队
		if (ret->left)
		{
			QueuePush(&q, ret->left);
		}
		if (ret->right)
		{
			QueuePush(&q, ret->right);
		}
	}
	QueueDestroy(&q);
}

3.11判断二叉树是否是完全二叉树

// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTNode* root)
{
	//这个都不能用递归了了
	//这个也是和层序遍历是一样的,但不同的是,孩子为空指针也会入队,当出队的为空指针时,队列中还有
	//非空指针,那就不是,如果后面全是空指针,那就是完全二叉树
	Queue q;
	QueueInit(&q);
	if (root == NULL)
		return true;
	QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		//出一个
		BTNode* ret = QueueFront(&q);
		QueuePop(&q);
		if (ret == NULL)
		{
			break;
		}
		QueuePush(&q, ret->left);
		QueuePush(&q, ret->right);
	}
	while (!QueueEmpty(&q))
	{
		//出一个
		BTNode* ret = QueueFront(&q);
		QueuePop(&q);
		if (ret != NULL)
		{
			QueueDestroy(&q);
			return false;
		}
	}
	QueueDestroy(&q);
	return true;
}

4.二叉树相关OJ题

4.1单值二叉树

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
// bool isUnivalTree(struct TreeNode* root) {
//     //如何实现,只需要判断每个节点等不等于它的左右孩子就可以了
//     //递归的话就是看每个子树满不满足单值了
//     //然后再看结束条件
//     //结束条件就是NULL return true,根不等于左或者右就返回false,但是左右肯定要不为空,不然怎么访问数据,如果根等于就递归
//     if (root == NULL)
//     {
//         return true;
//     }
//     if (root->left && root->val != root->left->val)
//     {
//         return false;
//     }
//     if (root->right && root->val != root->right->val)
//     {
//         return false;
//     }
//     return isUnivalTree(root->left) && isUnivalTree(root->right);
// }

  bool my_isUnivalTree(struct TreeNode* root, int x)
  {
      //递归的话,就是看左右子树是否同时为单值树
      //结束条件的话就是NULL返回true,不等于就返回false,等于就没事,因为就一个节点等于也说明不了什么
      if (root == NULL)
      {
          return true;
      }
      if (root->val != x)
      {
          return false;
      }
      return my_isUnivalTree(root->left,x) && my_isUnivalTree(root->right,x);
}
bool isUnivalTree(struct TreeNode* root) {
    //方法二,看每个节点等不等于那个值,为了让那个值一直存在,我们在建立一个函数
    return my_isUnivalTree(root, root->val);
  }

4.2二叉树的最大深度

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
int maxDepth(struct TreeNode* root) {

    //大事化小
    //如果为空就返回0,不为空的话就返回1+子树的长度中的那个较大值,而子树的长度就是与根相同的思路
    //停止递归的条件就是NULL
    if (root == NULL)
    {
        return 0;
    }
    //记录子树的长度,不然会多次递归
    int left_len = maxDepth(root->left);
    int right_len = maxDepth(root->right);
    if (left_len > right_len)
    {
        return 1 + left_len;
    }
    else
    {
        return 1 + right_len;
    }
}

4.3二叉树的前序遍历

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
  int TreeSize(struct TreeNode* root)
  {
      if (root == NULL)
      {
          return 0;
      }
      return 1 + TreeSize(root->left) + TreeSize(root->right);
  }
  void my_preorderTraversal(struct TreeNode* root, int* arr, int* pi)
  {
      //因为先序,所以先看根
      //根如果为空的话就什么都不干,不为空的话就赋值到数组中
      //然后再赋值左右子树,左右子树和根是一样的
      if (root == NULL)
      {
          return;
      }
      arr[*pi] = root->val;
      (*pi)++;
      my_preorderTraversal(root->left, arr, pi);
      my_preorderTraversal(root->right, arr, pi);
  }

int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    //按照题意,必须开辟一个数组,所以不能递归这个函数,不然一直开辟,所以在创建函数
    //开辟多大呢,还要先求有多少个
    int size = TreeSize(root);
    int* arr = (int*)malloc(sizeof(int) * size);
    //还要一个东西来记录下标,并且会一直变的,所以要取地址
    int i = 0;
    my_preorderTraversal(root, arr, &i);

    *returnSize = size;
    return arr;
}

4.4相同的树

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    //判断两个树是不是相同的树的话,就先判断根是不是相同的树
    //在判断两个子树是不是相同的树,而两个子树的判断的逻辑与根是相同的,这就叫大事化小

    //因为要两个子树同时为相同的树,才是真正的树,所以用&&,再加上返回又不是地址之类的,不用再设变量去保存返回值了
    
    //接下来再来看,递归停止条件,停止条件就是两个数值不相等的话就返回错误
    //而在使用两个数值之前就要看他们是不是空,一个为空都不能看数值
    //两个均为空,返回正确(说明前面的都相同了),一个空一个不为空就返回错误,这是处理空的时候,

    if (p == NULL && q == NULL)
    {
        return true;
    }
    //走到这里已经说明了两个不同时为NULL了
    //至少有一个为NULL
    if (p == NULL || q == NULL)
    {
        return false;
    }
    //根相同根本不能说明什么,要子树也相同才可以
    //不相同就说明返回错误
    if (p->val != q->val)
    {
        return false;
    }
    return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}

4.5对称二叉树

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
  bool my_isSymmetric(struct TreeNode* left, struct TreeNode* right)
  {
      //其实看是不是对称的,一定程度上就是看两个子树的某些子树是不是相同的
      //这里我们要递归的话,先看两个头相不相同
      // 
      //相同的话的话,就就看左的右,右的左两个相不相同,而这两个也可以递归,还有左的左,右的右,两者要同时相同才可以
      if (left == NULL && right == NULL)
      {
          return true;
      }
      if (left == NULL || right == NULL)
      {
          return false;
      }
      if (left->val != right->val)
      {
          return false;
      }
        return my_isSymmetric(left->right, right->left)&&my_isSymmetric(left->left, right->right);
  }
bool isSymmetric(struct TreeNode* root) {
    //递归的话就是,先看根,如果根相同,就看左子树与右子树是不是对称的//单独用个函数
    if (root == NULL)
    {
        return true;
    }
    return my_isSymmetric(root->left, root->right);
}

4.6另一棵树的子树

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


  bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
      //判断两个树是不是相同的树的话,就先判断根是不是相同的树
      //在判断两个子树是不是相同的树,而两个子树的判断的逻辑与根是相同的,这就叫大事化小

      //因为要两个子树同时为相同的树,才是真正的树,所以用&&,再加上返回又不是地址之类的,不用再设变量去保存返回值了

      //接下来再来看,递归停止条件,停止条件就是两个数值不相等的话就返回错误
      //而在使用两个数值之前就要看他们是不是空,一个为空都不能看数值
      //两个均为空,返回正确(说明前面的都相同了),一个空一个不为空就返回错误,这是处理空的时候,

      if (p == NULL && q == NULL)
      {
          return true;
      }
      //走到这里已经说明了两个不同时为NULL了
      //至少有一个为NULL
      if (p == NULL || q == NULL)
      {
          return false;
      }
      //根相同根本不能说明什么,要子树也相同才可以
      //不相同就说明返回错误
      if (p->val != q->val)
      {
          return false;
      }
      return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
  }
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot) {
    //这道题递归的话就是看以这个节点为根的话,这个树与subroot是不是相同的树,相同的话就ok,不相同的话就继续看左右孩子为根的树是不是,有一个就可以了,所以||
    if (root == NULL)
    {
        return false;
    }
    if (root->val==subRoot->val&&isSameTree(root, subRoot))//增加第一个条件的话,一定程度上可以减少好多次第二个条件的执行
    {
        return true;
    }
    return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}

4.7二叉树遍历

在这里插入图片描述

#include <stdio.h>
#include<stdlib.h>

struct TreeNode
{
    char val;
    struct TreeNode*left;
    struct TreeNode*right;
};

void PreOrderTree(struct TreeNode*tree)
{
    if(tree==NULL)
    {
        return;
    }
    PreOrderTree(tree->left);//左
    printf("%c ",tree->val);//根
    PreOrderTree(tree->right);//右
}
struct TreeNode* TreeCreat(struct TreeNode*tree,char*arr,int*i)
{
    //因为先序遍历,所以先序递归
    //先创建头,先创建根
    //再创建左右孩子,而且左右孩子的创建与根是一样的
    //最后再返回头

    //停止条件,第一NULL不为#创建,第二数组值为#,不创建,而且它肯定没子树了,
    //什么都不用干,但要返回NULL了,因为它是某个非空的孩子

    if(arr[*i]=='#')//
    {
        (*i)++;
        return NULL;
    }
    //创建根,但是要tree不为空才创建//因为先序遍历,所以有可能到因为创建过的节点
    if(tree==NULL)//创建
    {
        tree=(struct TreeNode*)malloc(sizeof(struct TreeNode));
        tree->val=arr[*i];
        (*i)++;
        tree->left=tree->right=NULL;//这样才可以递归去创建,不然为随机值不好弄
        tree->left=TreeCreat(tree->left,arr,i);
        tree->right=TreeCreat(tree->right,arr,i);
    }
    return tree;//左右都安排好了就直接返回了
}
int main() {
    //首先先创建这个数组
    char arr[100]={0};
    scanf("%s",arr);
    //创建树
    struct TreeNode*tree;
    tree=NULL;
    //主要函数
    //因为要把数组的值打入创建树//所以还要传下标
    int i=0;
    tree=TreeCreat(tree,arr,&i);
    PreOrderTree(tree);
    return 0;
}

4.8翻转二叉树

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
 /*
  void my_invertTree(struct TreeNode* left, struct TreeNode* right)
  {
      //翻转左右子树的话,就直接先翻转两个根,再翻转左的左,右的右,,,,,左的右,右的左,先假设翻转的时候同时有数据,同时为空
      //看来这样不行,因为不会同时为空,同时又数据,所以交换数据是不行的,要交换指针
      if (left == NULL && right == NULL)
      {
          return;
      }
      int tmp = left->val;
      left->val = right->val;
      right->val = tmp;
      my_invertTree(left->left, right->right);
      my_invertTree(left->right, right->left);
  }
struct TreeNode* invertTree(struct TreeNode* root) {
    //翻转这个树,就只需要翻转这颗树的左右子树就可以了
    if (root == NULL)
    {
        return NULL;
    }
    my_invertTree(root->left, root->right);
    return root;
}
*/
  struct TreeNode* invertTree(struct TreeNode* root) {
      //先交换左右子树,在交换左右子树的左右子树就可以了
      if (root == NULL)
      {
          return NULL;
      }
      struct TreeNode* tmp = root->left;
      root->left = root->right;
      root->right = tmp;
      invertTree(root->left);
      invertTree(root->right);
    return root;
  }

4.9平衡二叉树

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
//   int Height(struct TreeNode* root)
//   {
//       if (root == 0)
//       {
//           return 0;
//       }
//       int h1 = Height(root->left);
//       int h2 = Height(root->right);
//       if (h1 > h2)
//       {
//           return h1 + 1;
//       }
//       else
//       {
//           return h2 + 1;
//       }
//   }
// bool isBalanced(struct TreeNode* root) {
//     //法一:对每一个节点的左右孩子求高度,看高度是否满足平衡二叉树
//     //每一个节点:先序遍历,求高度再来一个函数
    
//     //一个树是平衡二叉树,要由三个保证,第一左右子树是平衡二叉树(调用本函数),第二左右子树高度差不超过一(调用height函数),
//     //而左右子树是不是平衡二叉树,就同样思路

//     //什么时候停止呢,==NULL就返回TRUE,除此之外判断一样
//     if (root == NULL)//因为NULL无法访问孩子了
//     {
//         return true;
//     }
//       return (abs(Height(root->left) - Height(root->right))<=1) && isBalanced(root->left) && isBalanced(root->right);
// }

  int my_isBalanced(struct TreeNode* root)
  {
      if (root == NULL)
      {
          return 0;
      }
      int h1= my_isBalanced(root->left);//这里可以看出,递归其实就是把这个函数的意义正常在函数中使用
      int h2= my_isBalanced(root->right);//我这个函数的意义就是求树的高度,那么就正常调用这个函数去表示高度就可以了

      if (h1 == -1 || h2 == -1)//看左右子树是不是平衡二叉树
      {
          return -1;
      }
      if (abs(h1 - h2) > 1)
      {
          return -1;
      }
      //走到这里就是平衡二叉树了
      //返回两个高度的最大值
      int max = h1;
      if (h2 > h1)
      {
          max = h2;
      }
      return max + 1;
  }
bool isBalanced(struct TreeNode* root) {
    //改进一下,如果是平衡二叉树就返回树的高度,而树的高度就是真
    //如果不是平衡二叉树就返回-1,因为NULL返回0,因为NULL是平衡二叉树,,,,,,但这样的话就会与bool的真值矛盾
    //所以在创建一个函数吧

    //而是不是平衡二叉树的判断就是两点,第一左右子树是平衡二叉树,第二两个高度之差不超过一
   

    //这个方法的优点就是在计算高度时顺便就判断了是不是平衡二叉树
    if (my_isBalanced(root) == -1)
    {
        return false;
    }
    return true;
}

这里可以看出,递归其实就是把这个函数的意义正常在函数中使用。。。。。。。。这句话是精华啊!!!!

总结

内容很多很丰富,读者觉得什么有用就看什么吧,或者也可以自己按照题目做一遍题的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李树上有郁香没树

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值