【数据结构---26】树以及二叉树的基本概念

树的概念:

一种非线性的数据结构,它是由n个(n>=0)有限节点组成的一个具有层次关系的集合

与树相关的基本概念:

	深度:树中节点的最大层次
	
	双亲:若一个节点含有子节点,则这个节点是这个子节点的双亲节点
	
	子节点:一个节点含有的子树的根节点被称为这个节点的子节点
	
	兄弟:具有相同双亲节点的被称为兄弟节点
	
	叶节点:度为0的节点被称为叶节点

树的表示方式:

	孩子表示法,双亲表示法,孩子双亲表示法,孩子兄弟表示法

二叉树:

	 空树,根+根的左子树+根的右子树

特殊的二叉树:

	满二叉树:每一层的节点数都达到最大值,这个二叉树就是满二叉树

	完全二叉树:从上之下从左至右一次填满的二叉树,不可能存在只有右孩子没有左孩子

二叉树的五条特性:

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

	2.若规定只有根节点的二叉树深度为1,则深度为k的二叉树最大节点数是2^k-1
	
	3.对任意一颗二叉树,如果其叶节点个数为n0,度为2的非叶节点个数为n2,则有n0=n2+1

	4.具有n个节点的完全二叉树的深度k为log2(n+1)向上取整

	5.对于有n个节点的完全二叉树,如果按照从上至下从左至右的顺序对所有节点从0进行编号

	则对于序号为i的节点有:
	
		<1>.若i>0,双亲序号:(i-1)/2i=0,i为根节点编号,无双亲节点
	
		<2>.若2i+1<n,左孩子序号:2i+1,否则无左孩子
	
		<3>.若2i+2<n,右孩子序号:2i+2,否则无右孩子

二叉树的存储:

	顺序结构:完全二叉树(基本不会增加删除)

	链式结构:通过指针来表示节点与其孩子及双亲之间的关系,常用孩子表示法,孩子双亲表示法

二叉树顺序存储: 堆(是一棵完全二叉树),堆中的元素存储到一维数组中,对于任意节点如果该节点中小于(大于)其左右孩子,就把这种结构称为小堆(大堆)

堆的特性: 堆顶元素一定是堆中所有元素最大的(最小的)

堆序堆的实现:

结构类似于顺序表

调整堆序:

	int child=parent*2+1;默认child标记parent的左孩子
	
	因为完全二叉树某个节点只有一个孩子,该孩子一定是其双亲的左孩子

	向下调整:(调整的是以parent为根的子树)

	找出较小的孩子---左右孩子比较(左右孩子必须都存在,child+1<size)

	左孩子比右孩子大的话,child+=1

	双亲比较小的孩子大的话,交换双亲和孩子的顺序
	
	更新parent=child;chil=parent*2+1;

	2i+1已经大于size(数组节点个数),说明孩子不存在

创建堆的时间复杂度Nlog2(N)

堆的删除操作:

	堆里没有元素不删除

	有的话就删除堆顶元素-----

	堆顶元素和末尾元素交换
	
	size的值要更新-----对堆顶元素进行向下调整
	
	AdjustDown(heapdatatype*array,heapdatatype*size,0)

堆的插入操作:

	考虑空间是否放得下-----插入之后需要调整堆序-----向上调整,传的参数是孩子
	
	孩子小于双亲,需要交换-----child=parent;parent=(child-1)/2;
	
	循环终止条件child!=0;

	AdjusUp(hp->array,hp->size,hp->size-1);

扩容:

	申请新空间-----拷贝元素		

用堆的思想进行排序

	降序是小堆,升序是大堆-----HeapSort(array,sizeof(array)/sizeof(array[0]))

TOP K问题(海量数据)

	冒泡和堆排的话必须一次拿到所有的数据-----100亿数据需要40G内存空间
	
	直接遍历K次,需要多次IO,性能太差-----堆-----取前K个数据,建小堆
	
	从剩余的N-K个数据一次与堆顶的元素进行比较,然后选择是否替换

	比堆顶元素大的替换掉,最后堆里的K个元素都是最大的

堆的应用需要做到正背如流!!!!!!!!

二叉树的链式存储方式

二叉树的遍历: 按照某种特定的规则,对二叉树中的每一个节点进行相应的操作,并且每个节点只能操作一次

	前序遍历:	根--->根的左子树--->根的右子树

	中序遍历:	根的左子树--->根--->根的右子树

	后序遍历:	根的左子树--->根的右子树--->根

递归遍历,先遍历根,然后继续调用,传的参数是root根节点的左子树,然后继续调用,传root的右子树

求二叉树的节点个数:

	(根据二叉树的概念)	空树---0个	非空就递归求解
int Getsize(Node*Root)
{
	if(Root==NULL)
	{
		return 0;
	}
	return Getsize(Root->left)+Getsize(Root->right)+1;
}

二叉树的创建方式:

索引必须给地址,因为要把索引的值带出函数外!!!!!!

创建链式二叉树—>递归跳出条件(*index<size)—>先创建根节点,在创建根的左子树,在创建根的右子树

	要把创建的二叉树补全ABDCEF--->ABD###CE##F##

	#是我们给的空的节点的标记	

	修改跳出条件为(*index<size&&array[*index]!='#')

	`跳出条件有先后顺序,不可以写错!!!!!`

	索引遇到#之后还需要往后面走

	//创建根节点

	//(*index++),创建根的左子树

	//(*index++),创建根的右子树

	递归之后其实创建的都是根节点,所有根节点创建写(*index++);

把创建的函数封装起来,方便用户调用,参数加一个无效参数,避免你设置为#,他输入$

Q:根据两个遍历的结果,要求还原出来的二叉树
A:TO DO

二叉树的销毁方式:

	最后才可以销毁根节点,所以采用后序遍历规则

	销毁完所有的节点之后要把Root节点置空函数体内部修改形参的值,要传形参的地址

	所以销毁函数中传Root的地址!!!!!

二叉树的拷贝:

根据二叉树的概念,和创建的方法一样

查看二叉树中的叶子节点:

	左右子树没有孩子的节点称为叶子节点
if(Root==NULL)
{
	return 0;
}
if(Root->left==NULL&&Root->right==NULL)
{
	return 1;
}
return GetLeatCount(Root->left)+GetLeatCount(Root->right);
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值