【数据结构与算法】<==>二叉树下

 

目录

堆的应用

1.堆排序:

1. 建堆

2.向下调整的时间复杂度

3.向上调整建堆的时间复杂度

二叉树链式结构的实现

遍历操作

其他操作


堆的应用

1.堆排序:

堆排序即利用堆的思想来进行排序,总共分为两个步骤:

1. 建堆

升序:建大堆

序:建大堆(如果建小堆的话,小堆不一定有序,只是堆顶最小,那下一个最小的数呢?如何依次选最小的数据?就算是选出来了之后,结点之间的关系就全乱了,无法继续利用优势,只能重新建堆O(N),选出次小的数据,效率太低了)建大堆直接交换堆顶和最后一个,进行向下调整即可

降序:建小堆
2.堆利用堆删除思想来进行排序
建堆和堆删除中都用到了向下调整,因此掌握了向下调整,就可以完成堆排序。回顾一下向下调整的过程:
image-20220809232058329

这里的建堆,是直接用数组进行建堆,可以用向上调整算法进行建堆,也可以利用向下调整建堆,有什么区别?我们先来看代码的实现:

//建堆——a,利用向上调整建堆——O(N*logN)
	//直接插入
	/*for (int i = 1; i < n; i++)
	{
		AdjustUp(a, i);
	}*/
	//建完堆之后无序,我们排个序


	//建堆——向下调整建堆(从最后一个节点的父亲开始,开始向下调整,直到根)——O(N)
	for (int i = (n-1-1)/2; i>=0; i--)
	{
		AdjustDown(a, n, i);
	}

两种的时间复杂度不一样:向上调整建堆的时间复杂度是O(N*logN);向下调整建堆的时间复杂度是O(N)。所以我们选用的是向下调整算法进行建堆,关于向下调整算法时间复杂度的推导过程:

2.向下调整的时间复杂度

因为堆是完全二叉树,而满二叉树也是完全二叉树,此处为了简化使用满二叉树来证明 ( 时间复杂度本来看的 就是近似值,多几个节点不影响最终结果)

因此:建堆的时间复杂度为O(N) 

3.向上调整建堆的时间复杂度

 

了解完后我们下面来实现排序

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//向下调整
void swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
void adjustdown(int* a, int n, int parent)
{
	//默认左孩子为最小值
	int minchild = parent * 2 + 1;
	while (minchild < n)
	{
		if (minchild + 1 < n && a[minchild] > a[minchild + 1])
		{
			minchild++;
		}
		if (a[minchild] < a[parent])
		{
			swap(&a[minchild], &a[parent]);
			parent = minchild;
			minchild = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
//建堆
void HeapSort(int* a, int n)
{
	//建堆——a,利用向上调整建堆
	//直接插入
	/*for (int i = 1; i < n; i++)
	{
		AdjustUp(a, i);
	}*/
	//建完堆之后无序,我们排个序


	//建堆——向下调整建堆(从最后一个节点的父亲开始,开始向下调整,直到根)
	int i = 0;
	for (i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		adjustdown(a, n, i);
	}
	//选数
	i = 1;
	while (i < n)
	{
		swap(&a[0], &a[n - i]);
		adjustdown(a, n - i, 0);
		i++;
	}
}
int main()
{

	int a[] = { 15,1,19,25,8,34,65,4,27,7 };
	HeapSort(a, sizeof(a) / sizeof(int));

	for (int i = 0; i < sizeof(a) / sizeof(int); i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
	return 0;
	
}

这里建的是小堆所以是降序 

 

二叉树链式结构的实现

在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。为了降低学习成本,此处手动快速创建一棵简单的二叉树,这里以简单的实现为主。后续在来讨论其创建方式

image-20220810163832470

#define  _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef int BTDataType;

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


BTNode* CreatTree()
{
	BTNode* n1 = (BTNode*)malloc(sizeof(BTNode));
	assert(n1);
	BTNode* n2 = (BTNode*)malloc(sizeof(BTNode));
	assert(n2);
	BTNode* n3 = (BTNode*)malloc(sizeof(BTNode));
	assert(n3);
	BTNode* n4 = (BTNode*)malloc(sizeof(BTNode));
	assert(n4);
	BTNode* n5 = (BTNode*)malloc(sizeof(BTNode));
	assert(n5);
	BTNode* n6 = (BTNode*)malloc(sizeof(BTNode));
	assert(n6);

	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;
	n5->data = 5;
	n6->data = 6;

	n1->left = n2;
	n1->right = n4;
	n2->left = n3;
	n2->right = NULL;
	n3->left = NULL;
	n3->right = NULL;
	n4->left = n5;
	n4->right = n6;
	n5->left = NULL;
	n5->right = NULL;
	n6->left = NULL;
	n6->right = NULL;

	return n1;
}

int main()
{
	BTNode* root = CreatTree();
	return 0;
}

这就大概搭建起了二叉树的框架,下面,来说一说其操作:

遍历操作

先序、中序、后序遍历递归操作:
//前序
void PreOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	printf("%d ", root->data);
	PreOrder(root->left);
	PreOrder(root->right);
}
//中序
void InOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	InOrder(root->left);
	printf("%d ", 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);
}

我们不难发现,二叉树的遍历操作通过递归实现非常地简单,实现并不难,但是你真的理解了吗函数怎么执行的(我们这里以前序遍历为例)

image-20220810165526334

image-20220810165556180

 完整代码

#define  _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef int BTDataType;

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


BTNode* CreatTree()
{
	BTNode* n1 = (BTNode*)malloc(sizeof(BTNode));
	assert(n1);
	BTNode* n2 = (BTNode*)malloc(sizeof(BTNode));
	assert(n2);
	BTNode* n3 = (BTNode*)malloc(sizeof(BTNode));
	assert(n3);
	BTNode* n4 = (BTNode*)malloc(sizeof(BTNode));
	assert(n4);
	BTNode* n5 = (BTNode*)malloc(sizeof(BTNode));
	assert(n5);
	BTNode* n6 = (BTNode*)malloc(sizeof(BTNode));
	assert(n6);

	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;
	n5->data = 5;
	n6->data = 6;

	n1->left = n2;
	n1->right = n4;
	n2->left = n3;
	n2->right = NULL;
	n3->left = NULL;
	n3->right = NULL;
	n4->left = n5;
	n4->right = n6;
	n5->left = NULL;
	n5->right = NULL;
	n6->left = NULL;
	n6->right = NULL;

	return n1;
}
//前序
void PreOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	printf("%d ", root->data);
	PreOrder(root->left);
	PreOrder(root->right);
}
//中序
void InOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	InOrder(root->left);
	printf("%d ", 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 main()
{
	BTNode* root = CreatTree();
	PreOrder(root);
	printf("\n");
	InOrder(root);
	printf("\n");
	PostOrder(root);
	return 0;
}

其他操作

结点个数

//结点个数
int TreeSize(BTNode* root)
{
	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);
}

高度

//高度

int TreeHeighrt(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	int left = TreeHeighrt(root->left);
	int right = TreeHeighrt(root->right);
	return left > right ? left + 1 : right + 1;
}

 

求第K层结点个数

//k层的结点数
int TreeLeveL(BTNode* root, int k)
{
	assert(k > 0);
	if (root == NULL)
	{
		return 0;
	}
	if (k == 1)
	{
		return 1;
	}
	return TreeLeveL(root->left, k - 1) + TreeLeveL(root->right, k - 1);
}

 

返回x所在的结点

//返回X所在的结点
BTNode* TreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
		return NULL;
	if (root->data == x)
		return root;
	//先去左树找
	BTNode* left = TreeFind(root->left, x);
	if (left != NULL)
		return left;
	//左树找不到,在去右树找
	BTNode* right = TreeFind(root->right, x);
	if (right != NULL)
		return right;
	return NULL;
}

 

完整代码

#define  _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef int BTDataType;

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


BTNode* CreatTree()
{
	BTNode* n1 = (BTNode*)malloc(sizeof(BTNode));
	assert(n1);
	BTNode* n2 = (BTNode*)malloc(sizeof(BTNode));
	assert(n2);
	BTNode* n3 = (BTNode*)malloc(sizeof(BTNode));
	assert(n3);
	BTNode* n4 = (BTNode*)malloc(sizeof(BTNode));
	assert(n4);
	BTNode* n5 = (BTNode*)malloc(sizeof(BTNode));
	assert(n5);
	BTNode* n6 = (BTNode*)malloc(sizeof(BTNode));
	assert(n6);

	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;
	n5->data = 5;
	n6->data = 6;

	n1->left = n2;
	n1->right = n4;
	n2->left = n3;
	n2->right = NULL;
	n3->left = NULL;
	n3->right = NULL;
	n4->left = n5;
	n4->right = n6;
	n5->left = NULL;
	n5->right = NULL;
	n6->left = NULL;
	n6->right = NULL;

	return n1;
}
//前序
void PreOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	printf("%d ", root->data);
	PreOrder(root->left);
	PreOrder(root->right);
}
//中序
void InOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	InOrder(root->left);
	printf("%d ", 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 TreeSize(BTNode* root)
{
	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);
}
//高度

int TreeHeighrt(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	int left = TreeHeighrt(root->left);
	int right = TreeHeighrt(root->right);
	return left > right ? left + 1 : right + 1;
}
//k层的结点数
int TreeLeveL(BTNode* root, int k)
{
	assert(k > 0);
	if (root == NULL)
	{
		return 0;
	}
	if (k == 1)
	{
		return 1;
	}
	return TreeLeveL(root->left, k - 1) + TreeLeveL(root->right, k - 1);
}
//返回X所在的结点
BTNode* TreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
		return NULL;
	if (root->data == x)
		return root;
	//先去左树找
	BTNode* left = TreeFind(root->left, x);
	if (left != NULL)
		return left;
	//左树找不到,在去右树找
	BTNode* right = TreeFind(root->right, x);
	if (right != NULL)
		return right;
	return NULL;
}

int main()
{
	BTNode* root = CreatTree();
	PreOrder(root);
	printf("\n");
	InOrder(root);
	printf("\n");
	PostOrder(root);
	printf("\n");
	printf("Size:%d\n", TreeSize(root));
	printf("LeafSize:%d\n", TreeLeafSize(root));
	printf("LeafHeighrt:%d\n", TreeHeighrt(root));
	printf("TreeLeveL:%d\n", TreeLeveL(root,3));
	printf("Tree Find:%p\n", TreeFind(root, 8));

	return 0;
}

 

 

  • 77
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 100
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 100
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

旧梦拾遗186

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

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

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

打赏作者

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

抵扣说明:

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

余额充值