树二叉树堆

Posted 勤奋的懒羊羊~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树二叉树堆相关的知识,希望对你有一定的参考价值。

目录

 

一、树的表示

二、二叉树的概念及结构

1、概念:

2、特殊的二叉树

3、二叉树的存储结构

 三、堆

1、大\\小根堆

2、堆的实现

1)结构及初始化

 2)插入

3)删除

4)取堆顶数据

5)判空

6)大小

7)销毁

四、堆排序


一、树的表示

常用:孩子兄弟表示法

typedef int DataType
struct Node

    struct Node*_firstchildren1;//第一个孩子结点
    struct Node*_pNextBrother;//指向下一个兄弟结点
    DataType _data;//结点中的数据域
;

二、二叉树的概念及结构

1、概念:

一颗二叉树是结点的一个有限集合,该集合:

1)为空

2)由一个根节点加上左子树和右子树的二叉树组成。

注意:二叉树子树有左右之分,次序不能颠倒,因此二叉树是有序树。

2、特殊的二叉树

1)满二叉树:每一层的结点数都达到最大值。如果层数为k,则该满二叉树的结点总数为2^k-1

2)完全二叉树:最后一层可以不满,但必须从左到右连续。

        如果满二叉树的高度为h,则它的结点数为2^h-1

        反之,如果满二叉树的结点有N个,则它的高度h为logN+1,可以看成logN。 

        高度为h的完全二叉树的结点数量范围是【2^(h-1),2^h-1】

对于任意一棵二叉树,度为0的永远比度为2的多一个。(每增加一个度为2的,就会增加一个度为0的)

3、二叉树的存储结构

父子下标关系:

parent=(child-1)/2

child左=parent*2+1

child右=parent*2+2

但是,当二叉树不是满二叉树或完全二叉树时,会浪费空间,不适合用数组存储表示二叉树。

 三、堆

1、大\\小根堆

小根堆:堆中某个结点总是不小于其父结点。

大根堆:堆中某个结点总是不大于其父结点。

堆一定是完全二叉树。

2、堆的实现

1)结构及初始化

typedef int HPDataType;
typedef struct Heap

	HPDataType* a;
	int size;
	int capacity;
HP;

void HeapInit(HP* php)

	assert(php);
	php->a = (HPDataType*)malloc(sizeof(HPDataType) * 4);
	if (php->a == NULL)
	
		perror("malloc failed");
		return;
	
	php->size = 0;
	php->capacity = 4;

 2)插入

插入数据的关键是在数组中插入数据后调整数据位置,这里我们实现的是大堆,所以当孩子大于父亲的时候,就应该交换位置。

void HeapPush(HP* php, HPDataType x)

	assert(php);
	if (php->capacity == php->size)
	
		HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * php->capacity * 2);
		if (tmp == NULL)
		
			perror("realloc failed");
			return;
		
		php->a = tmp;
		php->capacity *= 2;
	
	php->a[php->size] = x;//size就是最后一个数据的下一个数据的下标
	php->size++;
	AdjustUp(php->a,php->size-1);
void AdjustUp(HPDataType* a, int child)

	int parent = (child - 1) / 2;
	while (child > 0)
	
		if (a[child] > a[parent])
		
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		
		else
		
			break;
		
	
void Swap(HPDataType* p1, HPDataType* p2)

	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;

3)删除

要删除堆顶的数据,可以让顶数据与最后一个数据先交换位置,再向下调整顶数据的位置

如果它小于它的较大孩子,就让他们换位置

void HeapPop(HP* php)//删堆顶

    assert(php);
    assert(!HeapEmpty(php));
    Swap(&php->a[php->size-1], &php->a[0]);
    php->size--;
    AdjustDown(php->a,php->size,0);
void AdjustDown(HPDataType*a,int n,int parent)

	int child = parent * 2 + 1;
	while (child < n)
	
		//选出左右孩子中大的那一个
		//a[child + 1] > a[child] && child + 1 < n 不能这样写!
		//a[child + 1]已经越界访问了
		if (child + 1 < n && a[child + 1] > a[child])
		
			child++;
		
		if (a[child] > a[parent])
		
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		
		else
		
			break;
		

	

4)取堆顶数据

HPDataType HeapTop(HP* php)

	assert(php);
	return php->a[0];

5)判空

bool HeapEmpty(HP* php)

	assert(php);
	return php->size == 0;

6)大小

int HeapSize(HP* php)

	assert(php);
	return php->size;

7)销毁

void HeapDestroy(HP* php)

	assert(php);
	free(php->a);
	free(php);

四、堆排序

要想利用堆来给一组数排序

第一步:建堆(利用堆插入数据的过程,一个个插入)

第二步:排升序,建大堆;排降序,建小堆。

以排升序为例:

end一开始指向3, 当3和20互换且3的位置调整好后,20的位置就定下来了,

如何再让end=end-1,此时end指向5,再让5与第一个数交换调整……

void HeapSort(int* a,int n)

	//向上调整建堆
	for (int i = 0; i < n; i++)
	
		AdjustUp(a, i);
	

	int end = n - 1;
	while (end > 0)
	
		Swap(&a[end], &a[0]);
		AdjustDown(a, end, 0);
		end--;
	

扩展:建堆也可以用向下调整建堆

 

以上是关于树二叉树堆的主要内容,如果未能解决你的问题,请参考以下文章

C语言 - 数据结构树二叉树(上篇)

数据结构----树二叉树----c++ && python

数据结构

树型结构大总结

js数据结构与算法(二叉树二叉查找树)

数据结构-树二叉树的相关算法