【数据结构】树以及堆的讲解

这篇具有很好参考价值的文章主要介绍了【数据结构】树以及堆的讲解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

(这里写自定义目录标题)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

树形结构是一种非线性的数据结构,其应用非常广泛,由树形结构可以引申出二叉树、堆等等的特殊树。
学习树对我们今后的工作帮助非常大。

一、树的概念?

树是一种非线性的数据结构,它是n(n>=0)个有限结点组成的一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它根朝上,而叶朝下。简单来讲就是–>树+人类亲缘关系描述
【数据结构】树以及堆的讲解

**- 根结点:没有父结点,且为所有结点的祖先的结点,如上图的A

  • 节点的度:一个节点含有的子树个数称为该节点的度,如上图:A-6、D-1、E-2
  • 叶子节点:度为0的结点,如上图的B、C
  • 分支节点:度不为0的结点,如上图的D、E、F
  • 父节点:一个节点含有子节点的节点,称为父节点,如:A为B、C、D、E的父节点
  • 子节点:一个节点有父节点的节点称为子节点,如:B、C、D、E为A的子节点
  • 兄弟节点:具有相同父节点的节点,如:I、J的父节点都为E,则I和J为兄弟节点
  • 树的度:一棵树中,最大的节点度,如上图:树的度为6
  • 节点的层次:从根节点开始算,根为1,依次往下计算
  • 树的高度或深度:树的节点最大层,如上图:4
  • 堂兄弟:处于同一层,但又不是兄弟节点的节点
  • 节点的祖先:从根节点到所经分支上的所有节点
  • 子孙:以某节点为根的子树中任一节点都称为该节点的子孙,如:所有节点都是A的子孙
  • 森林:由多棵不相交的数组成**

二、树的表示方法

树的存储表示既要保存值域,也要保存节点和节点之间的关系,实际中树的表示方法有很多种,如:双亲表示法、孩子表示法等等,但我们最常用的还是孩子兄弟表示法。
【数据结构】树以及堆的讲解
【数据结构】树以及堆的讲解

三、树的实际应用

【数据结构】树以及堆的讲解
在实际应用中,树结构常常用于制作文件目录

四、二叉树概念以及结构

1.概念

一棵二叉树是结点的一个有限集合,构成二叉树有规定:
1.一定是由一个根节点加上两棵左子树和右子树组成
2.二叉树不存在大于2的节点
3.二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树

2.特殊的二叉树

  1. 满二叉树
    【数据结构】树以及堆的讲解
    每一层的节点数都达到最大值,则称这个二叉树为满二叉树,就是说,如果一个二叉树层数为h,且节点总数为2^h-1,则为满二叉树
    【数据结构】树以及堆的讲解
    2.完全二叉树
    【数据结构】树以及堆的讲解
    完全二叉树为(最后一层-1)层必须为满节点,最后一层可以没有分支节点,若有,则需要有序。
    注意:满二叉树是一种特殊的完全二叉树
    【数据结构】树以及堆的讲解

3.二叉树的性质

3.1 如何计算高度为h的节点个数?
【数据结构】树以及堆的讲解
3.2 如何计算二叉树的高度(h)
已知节点个数,求高度(h)
N为节点个数
公式:(2^h)-1 = N ⇒ F(h) = log N+1;

4.二叉树的存储结构

  1. 顺序存储
    顺序结构存储就是用数组进行存储,但一般用数组进行存储只用来存储完全二叉树,因为不是完全二叉树会有空间浪费,起原因是完全二叉树的子树必须是一个接着一个的,而其它形式的没这种规定
    【数据结构】树以及堆的讲解
    父子间下标关系:
    【数据结构】树以及堆的讲解

5.引入堆的概念以及结构

1.二叉树的顺序结构
普通的二叉树是不适合用数组来存储的,因为会浪费大量的空间,而往往在现实中,我们会把堆(一种二叉树)使用顺序结构的数组进行存储。
2.堆
2.1、是一种完全二叉树。
2.2、大堆:树中任何一个父亲都大于或等于孩子
【数据结构】树以及堆的讲解
小堆:树中任何一个父亲都小于或等于孩子
【数据结构】树以及堆的讲解

6.堆的实现以及堆排序

核心算法:

6.1 向上调整算法
前提:是一个堆
【数据结构】树以及堆的讲解

6.2 向下调整算法
前提:左右子树是一个堆
【数据结构】树以及堆的讲解

7.时间复杂度问题

向上调整建堆:
【数据结构】树以及堆的讲解
向下调整建堆
【数据结构】树以及堆的讲解
堆排序
【数据结构】树以及堆的讲解

8.TPopk问题

什么是TPopk问题?
TPopk问题是堆的应用之一,其是要实现N个数中找出最大/最小数的前K个.

实现方法:
1.用于简单场景,如N的值不大的情况
【数据结构】树以及堆的讲解

//找出前k个最大的数
void Swap(int* father, int* child)
{
	int tmp = *father;
	*father = *child;
	*child = tmp;
}
void AdjustDown(int* tpopk, int n,int father)
{
	int child = (father * 2) + 1;
	while (child<n)
	{
		if (child+1<n && tpopk[child]<tpopk[child+1])
		{
			child++;
		}
		if (tpopk[father] < tpopk[child])
		{
			Swap(&tpopk[father], &tpopk[child]);//交换
			father = child;
			child = (father * 2) + 1;
		}
		else
		{
			break;
		}
	}
}
void Adjustcreate(int* tpopk,int n)
{
	for (int i = (n-1-1)/2; i >=0; i--)
	{
		AdjustDown(tpopk,n,i);
	}
}
void AdjustPop(int* tpopk,int n)
{
	//交换首尾元素
	Swap(&(tpopk[0]), &(tpopk[n - 1]));
	n--;
	AdjustDown(tpopk, n, 0);
}
void TPopk(int* tpopk, int n)
{
	//1.建堆
	//采用向下调整建堆
	Adjustcreate(tpopk,n);

	//2.Tpop数据后,Pop数据
	printf("%d ", tpopk[0]);
	for (int i = 0; i < 4; i++)
	{
		AdjustPop(tpopk, n--);
		printf("%d ", tpopk[0]);
	}
}
int main()
{
	int tpopk[] = {5,2,9,6,1,4,10,50};
	int size = sizeof(tpopk) / sizeof(int);
	TPopk(tpopk,size);
	return 0;
}

2.用于复杂场景,如N的值太大的情况

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void Swap(int* child,int* father)
{
	int tmp = *child;
	*child = *father;
	*father = tmp;
}
void AdjustDown(int* a,int k,int father)
{
	int child = (father * 2) + 1;
	while (child<k)
	{
		if (child+1<k && a[child] >a[child+1])
		{
			child++;
		}
		if (a[child]<a[father])
		{
			Swap(&a[child],&a[father]);
			father = child;
			child = (father * 2) + 1;
		}
		else
		{
			break;
		}
	}
}
void AdjustDownC(int* a,int k)
{
	for (int i = (k-1-1)/2; i >=0; i--)
	{
		AdjustDown(a,k,i);
	}
}
void PrintTopK(int* a,int n,int k)
{
	//1.将前K个数建堆
	AdjustDownC(a,k);

	//2.将N-K的数,依次与堆顶元素比较
	for (int i = k; i < n; i++)
	{
		if (a[0] < a[i])
		{
			Swap(&a[0],&a[i]);
			AdjustDown(a,k,0);
		}
	}
	
}
void Topk()
{
	int n = 10000;
	int* a = (int*)malloc(sizeof(int) * n);
	if (a == NULL)
	{
		perror("malloc fail:");
		return;
	}
	srand((unsigned int)time(0));
	for (int i = 0; i < n; ++i)
	{
		a[i] = rand() % 100;
	}
	a[5] = 1000000 + 1;
	a[1231] = 1000000 + 2;
	a[531] = 1000000 + 3;
	a[5121] = 1000000 + 4;
	a[115] = 1000000 + 5;
	a[2335] = 1000000 + 6;
	a[9999] = 1000000 + 7;
	a[76] = 1000000 + 8;
	a[423] = 1000000 + 9;
	a[3144] = 1000000 + 10;
	PrintTopK(a, n, 10);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", a[i]);
	}

}
int main()
{
	Topk();
	return 0;
}

总结

这就是我对堆的应用与理解,谢谢观看!文章来源地址https://www.toymoban.com/news/detail-499552.html

到了这里,关于【数据结构】树以及堆的讲解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构学习分享之堆的详解以及TopK问题

    💓博主CSDN主页:杭电码农-NEO💓   ⏩专栏分类:数据结构学习分享⏪   🚚代码仓库:NEO的学习日记🚚   🌹关注我🫵带你了解更多数据结构的知识   🔝🔝 本章就给大家带来久违的堆的知识,如果你还不知道数的相关知识,或者什么是完全二叉树,请跳转 树的介绍, 本章的堆结

    2024年02月05日
    浏览(109)
  • 【数据结构】堆的实现,堆排序以及TOP-K问题

    目录 1.堆的概念及结构 2.堆的实现 2.1初始化堆 2.2销毁堆 2.3取堆顶元素 2.4返回堆的大小 2.5判断是否为空 2.6打印堆 2.7插入元素 2.8堆的向上调整 2.9弹出元素 2.10堆的向下调整 3. 建堆时间复杂度 4. 堆的应用 4.1 堆排序 4.2 TOP-K问题 堆是一种数据结构,它是由一组元素组成的,并

    2024年02月12日
    浏览(52)
  • 【数据结构】向上调整建堆和向下调整建堆的天壤之别以及堆排序算法

       💯 博客内容:【数据结构】向上调整建堆和向下调整建堆的天壤之别以及堆排序算法 😀 作  者:陈大大陈 🚀 个人简介:一个正在努力学技术的准前端,专注基础和实战分享 ,欢迎私信! 💖 欢迎大家:这里是CSDN,我总结知识和写笔记的地方,喜欢的话请三连,有

    2024年02月06日
    浏览(48)
  • postgresql 使用之 存储架构 触摸真实数据的存储结构以及组织形式,存入数据库的数据原来在这里

    ​ 专栏内容 : postgresql内核源码分析 手写数据库toadb 并发编程 个人主页 :我的主页 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物. postgresql 数据库服务运行时,数据在磁盘上是如何存储的呢?这就涉及到了存储架构。 在文件系统中,我们可以看到以目录和文

    2024年02月14日
    浏览(40)
  • 【数据结构】二叉树算法讲解(定义+算法原理+源码)

    博主介绍:✌全网粉丝喜爱+、前后端领域优质创作者、本质互联网精神、坚持优质作品共享、掘金/腾讯云/阿里云等平台优质作者、擅长前后端项目开发和毕业项目实战✌有需要可以联系作者我哦! 🍅附上相关C语言版源码讲解🍅 👇🏻 精彩专栏推荐订阅👇🏻 不然下次找

    2024年01月23日
    浏览(54)
  • 树的引进以及二叉树的基础讲解——【数据结构】

                                     W...Y的主页 😊 代码仓库分享  💕 当我们学习完前面的数据结构,难度也就会上升,但是这个也是非常重要的数据结构。今天我们来学习一种新的数据类型——树。 目录 树的概念以及结构 树的概念 树的相关概念 树的表示

    2024年02月07日
    浏览(44)
  • 【数据结构】堆的创建

    堆就是以二叉树的顺序存储方式来存储元素,同时又要满足父亲结点存储数据都要大于儿子结点存储数据或者父亲结点数据都要小于儿子结点数据的一种数据结构。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。 堆中某个节点的值总是不大于或

    2024年02月07日
    浏览(45)
  • 数据结构:堆的实现

    如果有一个关键码的集合 K = { k1 ,k2 ,k3 ,…,kn },把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并且 k(i)  k(i*2+1) 和 k(i)  k(i*2+2), i = 0 , 1 , 2…,则称为小堆 ( 或大堆 ) 。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小

    2024年02月13日
    浏览(35)
  • 数据结构---堆的实现

    前言 一、什么是堆? 二、 堆的实现 1. 堆的结构  2. 接口实现 总结 堆(Heap)是计算机科学中一类特殊的数据结构,是最高效的优先级队列。堆通常是一个可以被看做一棵完全二叉树的数组对象。 现实中我们通常把 堆(一种二叉树) 使用 顺序结构的数组 来存储, 大根堆 :根节

    2024年02月02日
    浏览(39)
  • 数据结构——堆的应用

    堆结构主要有两个应用:1、堆排序 2、topK问题 现实中,排序是非常常见的,比如排序班级同学的各科分数,购物时,商品会按销量,价格,好评数等进行排序。相信大家也不喜欢再购物筛选时,加载半天出不来吧!一个好的排序用的时间会大大减少,改善用户的体验。堆排

    2024年04月10日
    浏览(77)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包